

/**
 * jQuery.ScrollTo
 * Copyright (c) 2007-2009 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
 * Dual licensed under MIT and GPL.
 * Date: 5/25/2009
 *
 * @projectDescription Easy element scrolling using jQuery.
 * http://flesler.blogspot.com/2007/10/jqueryscrollto.html
 * Works with jQuery +1.2.6. Tested on FF 2/3, IE 6/7/8, Opera 9.5/6, Safari 3, Chrome 1 on WinXP.
 *
 * @author Ariel Flesler
 * @version 1.4.2
 *
 * @id jQuery.scrollTo
 * @id jQuery.fn.scrollTo
 * @param {String, Number, DOMElement, jQuery, Object} target Where to scroll the matched elements.
 *	  The different options for target are:
 *		- A number position (will be applied to all axes).
 *		- A string position ('44', '100px', '+=90', etc ) will be applied to all axes
 *		- A jQuery/DOM element ( logically, child of the element to scroll )
 *		- A string selector, that will be relative to the element to scroll ( 'li:eq(2)', etc )
 *		- A hash { top:x, left:y }, x and y can be any kind of number/string like above.
*		- A percentage of the container's dimension/s, for example: 50% to go to the middle.
 *		- The string 'max' for go-to-end. 
 * @param {Number} duration The OVERALL length of the animation, this argument can be the settings object instead.
 * @param {Object,Function} settings Optional set of settings or the onAfter callback.
 *	 @option {String} axis Which axis must be scrolled, use 'x', 'y', 'xy' or 'yx'.
 *	 @option {Number} duration The OVERALL length of the animation.
 *	 @option {String} easing The easing method for the animation.
 *	 @option {Boolean} margin If true, the margin of the target element will be deducted from the final position.
 *	 @option {Object, Number} offset Add/deduct from the end position. One number for both axes or { top:x, left:y }.
 *	 @option {Object, Number} over Add/deduct the height/width multiplied by 'over', can be { top:x, left:y } when using both axes.
 *	 @option {Boolean} queue If true, and both axis are given, the 2nd axis will only be animated after the first one ends.
 *	 @option {Function} onAfter Function to be called after the scrolling ends. 
 *	 @option {Function} onAfterFirst If queuing is activated, this function will be called after the first scrolling ends.
 * @return {jQuery} Returns the same jQuery object, for chaining.
 *
 * @desc Scroll to a fixed position
 * @example $('div').scrollTo( 340 );
 *
 * @desc Scroll relatively to the actual position
 * @example $('div').scrollTo( '+=340px', { axis:'y' } );
 *
 * @dec Scroll using a selector (relative to the scrolled element)
 * @example $('div').scrollTo( 'p.paragraph:eq(2)', 500, { easing:'swing', queue:true, axis:'xy' } );
 *
 * @ Scroll to a DOM element (same for jQuery object)
 * @example var second_child = document.getElementById('container').firstChild.nextSibling;
 *			$('#container').scrollTo( second_child, { duration:500, axis:'x', onAfter:function(){
 *				alert('scrolled!!');																   
 *			}});
 *
 * @desc Scroll on both axes, to different values
 * @example $('div').scrollTo( { top: 300, left:'+=200' }, { axis:'xy', offset:-20 } );
 */
;(function( $ ){
	
	var $scrollTo = $.scrollTo = function( target, duration, settings ){
		$(window).scrollTo( target, duration, settings );
	};

	$scrollTo.defaults = {
		axis:'xy',
		duration: parseFloat($.fn.jquery) >= 1.3 ? 0 : 1
	};

	// Returns the element that needs to be animated to scroll the window.
	// Kept for backwards compatibility (specially for localScroll & serialScroll)
	$scrollTo.window = function( scope ){
		return $(window)._scrollable();
	};

	// Hack, hack, hack :)
	// Returns the real elements to scroll (supports window/iframes, documents and regular nodes)
	$.fn._scrollable = function(){
		return this.map(function(){
			var elem = this,
				isWin = !elem.nodeName || $.inArray( elem.nodeName.toLowerCase(), ['iframe','#document','html','body'] ) != -1;

				if( !isWin )
					return elem;

			var doc = (elem.contentWindow || elem).document || elem.ownerDocument || elem;
			
			return $.browser.safari || doc.compatMode == 'BackCompat' ?
				doc.body : 
				doc.documentElement;
		});
	};

	$.fn.scrollTo = function( target, duration, settings ){
		if( typeof duration == 'object' ){
			settings = duration;
			duration = 0;
		}
		if( typeof settings == 'function' )
			settings = { onAfter:settings };
			
		if( target == 'max' )
			target = 9e9;
			
		settings = $.extend( {}, $scrollTo.defaults, settings );
		// Speed is still recognized for backwards compatibility
		duration = duration || settings.speed || settings.duration;
		// Make sure the settings are given right
		settings.queue = settings.queue && settings.axis.length > 1;
		
		if( settings.queue )
			// Let's keep the overall duration
			duration /= 2;
		settings.offset = both( settings.offset );
		settings.over = both( settings.over );

		return this._scrollable().each(function(){
			var elem = this,
				$elem = $(elem),
				targ = target, toff, attr = {},
				win = $elem.is('html,body');

			switch( typeof targ ){
				// A number will pass the regex
				case 'number':
				case 'string':
					if( /^([+-]=)?\d+(\.\d+)?(px|%)?$/.test(targ) ){
						targ = both( targ );
						// We are done
						break;
					}
					// Relative selector, no break!
					targ = $(targ,this);
				case 'object':
					// DOMElement / jQuery
					if( targ.is || targ.style )
						// Get the real position of the target 
						toff = (targ = $(targ)).offset();
			}
			$.each( settings.axis.split(''), function( i, axis ){
				var Pos	= axis == 'x' ? 'Left' : 'Top',
					pos = Pos.toLowerCase(),
					key = 'scroll' + Pos,
					old = elem[key],
					max = $scrollTo.max(elem, axis);

				if( toff ){// jQuery / DOMElement
					attr[key] = toff[pos] + ( win ? 0 : old - $elem.offset()[pos] );

					// If it's a dom element, reduce the margin
					if( settings.margin ){
						attr[key] -= parseInt(targ.css('margin'+Pos)) || 0;
						attr[key] -= parseInt(targ.css('border'+Pos+'Width')) || 0;
					}
					
					attr[key] += settings.offset[pos] || 0;
					
					if( settings.over[pos] )
						// Scroll to a fraction of its width/height
						attr[key] += targ[axis=='x'?'width':'height']() * settings.over[pos];
				}else{ 
					var val = targ[pos];
					// Handle percentage values
					attr[key] = val.slice && val.slice(-1) == '%' ? 
						parseFloat(val) / 100 * max
						: val;
				}

				// Number or 'number'
				if( /^\d+$/.test(attr[key]) )
					// Check the limits
					attr[key] = attr[key] <= 0 ? 0 : Math.min( attr[key], max );

				// Queueing axes
				if( !i && settings.queue ){
					// Don't waste time animating, if there's no need.
					if( old != attr[key] )
						// Intermediate animation
						animate( settings.onAfterFirst );
					// Don't animate this axis again in the next iteration.
					delete attr[key];
				}
			});

			animate( settings.onAfter );			

			function animate( callback ){
				$elem.animate( attr, duration, settings.easing, callback && function(){
					callback.call(this, target, settings);
				});
			};

		}).end();
	};
	
	// Max scrolling position, works on quirks mode
	// It only fails (not too badly) on IE, quirks mode.
	$scrollTo.max = function( elem, axis ){
		var Dim = axis == 'x' ? 'Width' : 'Height',
			scroll = 'scroll'+Dim;
		
		if( !$(elem).is('html,body') )
			return elem[scroll] - $(elem)[Dim.toLowerCase()]();
		
		var size = 'client' + Dim,
			html = elem.ownerDocument.documentElement,
			body = elem.ownerDocument.body;

		return Math.max( html[scroll], body[scroll] ) 
			 - Math.min( html[size]  , body[size]   );
			
	};

	function both( val ){
		return typeof val == 'object' ? val : { top:val, left:val };
	};

})( jQuery );

/*
 * jQuery UI Datepicker 1.8.11
 *
 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Datepicker
 *
 * Depends:
 *	jquery.ui.core.js
 */
(function( $, undefined ) {

$.extend($.ui, { datepicker: { version: "1.8.11" } });

var PROP_NAME = 'datepicker';
var dpuuid = new Date().getTime();

/* Date picker manager.
   Use the singleton instance of this class, $.datepicker, to interact with the date picker.
   Settings for (groups of) date pickers are maintained in an instance object,
   allowing multiple different settings on the same page. */

function Datepicker() {
	this.debug = false; // Change this to true to start debugging
	this._curInst = null; // The current instance in use
	this._keyEvent = false; // If the last event was a key event
	this._disabledInputs = []; // List of date picker inputs that have been disabled
	this._datepickerShowing = false; // True if the popup picker is showing , false if not
	this._inDialog = false; // True if showing within a "dialog", false if not
	this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
	this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
	this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
	this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
	this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
	this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
	this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
	this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
	this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
	this.regional = []; // Available regional settings, indexed by language code
	this.regional[''] = { // Default regional settings
		closeText: 'Done', // Display text for close link
		prevText: 'Prev', // Display text for previous month link
		nextText: 'Next', // Display text for next month link
		currentText: 'Today', // Display text for current month link
		monthNames: ['January','February','March','April','May','June',
			'July','August','September','October','November','December'], // Names of months for drop-down and formatting
		monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
		dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
		dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
		dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
		weekHeader: 'Wk', // Column header for week of the year
		dateFormat: 'mm/dd/yy', // See format options on parseDate
		firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
		isRTL: false, // True if right-to-left language, false if left-to-right
		showMonthAfterYear: false, // True if the year select precedes month, false for month then year
		yearSuffix: '' // Additional text to append to the year in the month headers
	};
	this._defaults = { // Global defaults for all the date picker instances
		showOn: 'focus', // 'focus' for popup on focus,
			// 'button' for trigger button, or 'both' for either
		showAnim: 'fadeIn', // Name of jQuery animation for popup
		showOptions: {}, // Options for enhanced animations
		defaultDate: null, // Used when field is blank: actual date,
			// +/-number for offset from today, null for today
		appendText: '', // Display text following the input box, e.g. showing the format
		buttonText: '...', // Text for trigger button
		buttonImage: '', // URL for trigger button image
		buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
		hideIfNoPrevNext: false, // True to hide next/previous month links
			// if not applicable, false to just disable them
		navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
		gotoCurrent: false, // True if today link goes back to current selection instead
		changeMonth: false, // True if month can be selected directly, false if only prev/next
		changeYear: false, // True if year can be selected directly, false if only prev/next
		yearRange: 'c-10:c+10', // Range of years to display in drop-down,
			// either relative to today's year (-nn:+nn), relative to currently displayed year
			// (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
		showOtherMonths: false, // True to show dates in other months, false to leave blank
		selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
		showWeek: false, // True to show week of the year, false to not show it
		calculateWeek: this.iso8601Week, // How to calculate the week of the year,
			// takes a Date and returns the number of the week for it
		shortYearCutoff: '+10', // Short year values < this are in the current century,
			// > this are in the previous century,
			// string value starting with '+' for current year + value
		minDate: null, // The earliest selectable date, or null for no limit
		maxDate: null, // The latest selectable date, or null for no limit
		duration: 'fast', // Duration of display/closure
		beforeShowDay: null, // Function that takes a date and returns an array with
			// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
			// [2] = cell title (optional), e.g. $.datepicker.noWeekends
		beforeShow: null, // Function that takes an input field and
			// returns a set of custom settings for the date picker
		onSelect: null, // Define a callback function when a date is selected
		onChangeMonthYear: null, // Define a callback function when the month or year is changed
		onClose: null, // Define a callback function when the datepicker is closed
		numberOfMonths: 1, // Number of months to show at a time
		showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
		stepMonths: 1, // Number of months to step back/forward
		stepBigMonths: 12, // Number of months to step back/forward for the big links
		altField: '', // Selector for an alternate field to store selected dates into
		altFormat: '', // The date format to use for the alternate field
		constrainInput: true, // The input is constrained by the current date format
		showButtonPanel: false, // True to show button panel, false to not show it
		autoSize: false // True to size the input for the date format, false to leave as is
	};
	$.extend(this._defaults, this.regional['']);
	this.dpDiv = $('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>');
}

$.extend(Datepicker.prototype, {
	/* Class name added to elements to indicate already configured with a date picker. */
	markerClassName: 'hasDatepicker',

	/* Debug logging (if enabled). */
	log: function () {
		if (this.debug)
			console.log.apply('', arguments);
	},
	
	// TODO rename to "widget" when switching to widget factory
	_widgetDatepicker: function() {
		return this.dpDiv;
	},

	/* Override the default settings for all instances of the date picker.
	   @param  settings  object - the new settings to use as defaults (anonymous object)
	   @return the manager object */
	setDefaults: function(settings) {
		extendRemove(this._defaults, settings || {});
		return this;
	},

	/* Attach the date picker to a jQuery selection.
	   @param  target    element - the target input field or division or span
	   @param  settings  object - the new settings to use for this date picker instance (anonymous) */
	_attachDatepicker: function(target, settings) {
		// check for settings on the control itself - in namespace 'date:'
		var inlineSettings = null;
		for (var attrName in this._defaults) {
			var attrValue = target.getAttribute('date:' + attrName);
			if (attrValue) {
				inlineSettings = inlineSettings || {};
				try {
					inlineSettings[attrName] = eval(attrValue);
				} catch (err) {
					inlineSettings[attrName] = attrValue;
				}
			}
		}
		var nodeName = target.nodeName.toLowerCase();
		var inline = (nodeName == 'div' || nodeName == 'span');
		if (!target.id) {
			this.uuid += 1;
			target.id = 'dp' + this.uuid;
		}
		var inst = this._newInst($(target), inline);
		inst.settings = $.extend({}, settings || {}, inlineSettings || {});
		if (nodeName == 'input') {
			this._connectDatepicker(target, inst);
		} else if (inline) {
			this._inlineDatepicker(target, inst);
		}
	},

	/* Create a new instance object. */
	_newInst: function(target, inline) {
		var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars
		return {id: id, input: target, // associated target
			selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
			drawMonth: 0, drawYear: 0, // month being drawn
			inline: inline, // is datepicker inline or not
			dpDiv: (!inline ? this.dpDiv : // presentation div
			$('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))};
	},

	/* Attach the date picker to an input field. */
	_connectDatepicker: function(target, inst) {
		var input = $(target);
		inst.append = $([]);
		inst.trigger = $([]);
		if (input.hasClass(this.markerClassName))
			return;
		this._attachments(input, inst);
		input.addClass(this.markerClassName).keydown(this._doKeyDown).
			keypress(this._doKeyPress).keyup(this._doKeyUp).
			bind("setData.datepicker", function(event, key, value) {
				inst.settings[key] = value;
			}).bind("getData.datepicker", function(event, key) {
				return this._get(inst, key);
			});
		this._autoSize(inst);
		$.data(target, PROP_NAME, inst);
	},

	/* Make attachments based on settings. */
	_attachments: function(input, inst) {
		var appendText = this._get(inst, 'appendText');
		var isRTL = this._get(inst, 'isRTL');
		if (inst.append)
			inst.append.remove();
		if (appendText) {
			inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
			input[isRTL ? 'before' : 'after'](inst.append);
		}
		input.unbind('focus', this._showDatepicker);
		if (inst.trigger)
			inst.trigger.remove();
		var showOn = this._get(inst, 'showOn');
		if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
			input.focus(this._showDatepicker);
		if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
			var buttonText = this._get(inst, 'buttonText');
			var buttonImage = this._get(inst, 'buttonImage');
			inst.trigger = $(this._get(inst, 'buttonImageOnly') ?
				$('<img/>').addClass(this._triggerClass).
					attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
				$('<button type="button"></button>').addClass(this._triggerClass).
					html(buttonImage == '' ? buttonText : $('<img/>').attr(
					{ src:buttonImage, alt:buttonText, title:buttonText })));
			input[isRTL ? 'before' : 'after'](inst.trigger);
			inst.trigger.click(function() {
				if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0])
					$.datepicker._hideDatepicker();
				else
					$.datepicker._showDatepicker(input[0]);
				return false;
			});
		}
	},

	/* Apply the maximum length for the date format. */
	_autoSize: function(inst) {
		if (this._get(inst, 'autoSize') && !inst.inline) {
			var date = new Date(2009, 12 - 1, 20); // Ensure double digits
			var dateFormat = this._get(inst, 'dateFormat');
			if (dateFormat.match(/[DM]/)) {
				var findMax = function(names) {
					var max = 0;
					var maxI = 0;
					for (var i = 0; i < names.length; i++) {
						if (names[i].length > max) {
							max = names[i].length;
							maxI = i;
						}
					}
					return maxI;
				};
				date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
					'monthNames' : 'monthNamesShort'))));
				date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
					'dayNames' : 'dayNamesShort'))) + 20 - date.getDay());
			}
			inst.input.attr('size', this._formatDate(inst, date).length);
		}
	},

	/* Attach an inline date picker to a div. */
	_inlineDatepicker: function(target, inst) {
		var divSpan = $(target);
		if (divSpan.hasClass(this.markerClassName))
			return;
		divSpan.addClass(this.markerClassName).append(inst.dpDiv).
			bind("setData.datepicker", function(event, key, value){
				inst.settings[key] = value;
			}).bind("getData.datepicker", function(event, key){
				return this._get(inst, key);
			});
		$.data(target, PROP_NAME, inst);
		this._setDate(inst, this._getDefaultDate(inst), true);
		this._updateDatepicker(inst);
		this._updateAlternate(inst);
		inst.dpDiv.show();
	},

	/* Pop-up the date picker in a "dialog" box.
	   @param  input     element - ignored
	   @param  date      string or Date - the initial date to display
	   @param  onSelect  function - the function to call when a date is selected
	   @param  settings  object - update the dialog date picker instance's settings (anonymous object)
	   @param  pos       int[2] - coordinates for the dialog's position within the screen or
	                     event - with x/y coordinates or
	                     leave empty for default (screen centre)
	   @return the manager object */
	_dialogDatepicker: function(input, date, onSelect, settings, pos) {
		var inst = this._dialogInst; // internal instance
		if (!inst) {
			this.uuid += 1;
			var id = 'dp' + this.uuid;
			this._dialogInput = $('<input type="text" id="' + id +
				'" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>');
			this._dialogInput.keydown(this._doKeyDown);
			$('body').append(this._dialogInput);
			inst = this._dialogInst = this._newInst(this._dialogInput, false);
			inst.settings = {};
			$.data(this._dialogInput[0], PROP_NAME, inst);
		}
		extendRemove(inst.settings, settings || {});
		date = (date && date.constructor == Date ? this._formatDate(inst, date) : date);
		this._dialogInput.val(date);

		this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
		if (!this._pos) {
			var browserWidth = document.documentElement.clientWidth;
			var browserHeight = document.documentElement.clientHeight;
			var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
			var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
			this._pos = // should use actual width/height below
				[(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
		}

		// move input on screen for focus, but hidden behind dialog
		this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px');
		inst.settings.onSelect = onSelect;
		this._inDialog = true;
		this.dpDiv.addClass(this._dialogClass);
		this._showDatepicker(this._dialogInput[0]);
		if ($.blockUI)
			$.blockUI(this.dpDiv);
		$.data(this._dialogInput[0], PROP_NAME, inst);
		return this;
	},

	/* Detach a datepicker from its control.
	   @param  target    element - the target input field or division or span */
	_destroyDatepicker: function(target) {
		var $target = $(target);
		var inst = $.data(target, PROP_NAME);
		if (!$target.hasClass(this.markerClassName)) {
			return;
		}
		var nodeName = target.nodeName.toLowerCase();
		$.removeData(target, PROP_NAME);
		if (nodeName == 'input') {
			inst.append.remove();
			inst.trigger.remove();
			$target.removeClass(this.markerClassName).
				unbind('focus', this._showDatepicker).
				unbind('keydown', this._doKeyDown).
				unbind('keypress', this._doKeyPress).
				unbind('keyup', this._doKeyUp);
		} else if (nodeName == 'div' || nodeName == 'span')
			$target.removeClass(this.markerClassName).empty();
	},

	/* Enable the date picker to a jQuery selection.
	   @param  target    element - the target input field or division or span */
	_enableDatepicker: function(target) {
		var $target = $(target);
		var inst = $.data(target, PROP_NAME);
		if (!$target.hasClass(this.markerClassName)) {
			return;
		}
		var nodeName = target.nodeName.toLowerCase();
		if (nodeName == 'input') {
			target.disabled = false;
			inst.trigger.filter('button').
				each(function() { this.disabled = false; }).end().
				filter('img').css({opacity: '1.0', cursor: ''});
		}
		else if (nodeName == 'div' || nodeName == 'span') {
			var inline = $target.children('.' + this._inlineClass);
			inline.children().removeClass('ui-state-disabled');
		}
		this._disabledInputs = $.map(this._disabledInputs,
			function(value) { return (value == target ? null : value); }); // delete entry
	},

	/* Disable the date picker to a jQuery selection.
	   @param  target    element - the target input field or division or span */
	_disableDatepicker: function(target) {
		var $target = $(target);
		var inst = $.data(target, PROP_NAME);
		if (!$target.hasClass(this.markerClassName)) {
			return;
		}
		var nodeName = target.nodeName.toLowerCase();
		if (nodeName == 'input') {
			target.disabled = true;
			inst.trigger.filter('button').
				each(function() { this.disabled = true; }).end().
				filter('img').css({opacity: '0.5', cursor: 'default'});
		}
		else if (nodeName == 'div' || nodeName == 'span') {
			var inline = $target.children('.' + this._inlineClass);
			inline.children().addClass('ui-state-disabled');
		}
		this._disabledInputs = $.map(this._disabledInputs,
			function(value) { return (value == target ? null : value); }); // delete entry
		this._disabledInputs[this._disabledInputs.length] = target;
	},

	/* Is the first field in a jQuery collection disabled as a datepicker?
	   @param  target    element - the target input field or division or span
	   @return boolean - true if disabled, false if enabled */
	_isDisabledDatepicker: function(target) {
		if (!target) {
			return false;
		}
		for (var i = 0; i < this._disabledInputs.length; i++) {
			if (this._disabledInputs[i] == target)
				return true;
		}
		return false;
	},

	/* Retrieve the instance data for the target control.
	   @param  target  element - the target input field or division or span
	   @return  object - the associated instance data
	   @throws  error if a jQuery problem getting data */
	_getInst: function(target) {
		try {
			return $.data(target, PROP_NAME);
		}
		catch (err) {
			throw 'Missing instance data for this datepicker';
		}
	},

	/* Update or retrieve the settings for a date picker attached to an input field or division.
	   @param  target  element - the target input field or division or span
	   @param  name    object - the new settings to update or
	                   string - the name of the setting to change or retrieve,
	                   when retrieving also 'all' for all instance settings or
	                   'defaults' for all global defaults
	   @param  value   any - the new value for the setting
	                   (omit if above is an object or to retrieve a value) */
	_optionDatepicker: function(target, name, value) {
		var inst = this._getInst(target);
		if (arguments.length == 2 && typeof name == 'string') {
			return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :
				(inst ? (name == 'all' ? $.extend({}, inst.settings) :
				this._get(inst, name)) : null));
		}
		var settings = name || {};
		if (typeof name == 'string') {
			settings = {};
			settings[name] = value;
		}
		if (inst) {
			if (this._curInst == inst) {
				this._hideDatepicker();
			}
			var date = this._getDateDatepicker(target, true);
			var minDate = this._getMinMaxDate(inst, 'min');
			var maxDate = this._getMinMaxDate(inst, 'max');
			extendRemove(inst.settings, settings);
			// reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
			if (minDate !== null && settings['dateFormat'] !== undefined && settings['minDate'] === undefined)
				inst.settings.minDate = this._formatDate(inst, minDate);
			if (maxDate !== null && settings['dateFormat'] !== undefined && settings['maxDate'] === undefined)
				inst.settings.maxDate = this._formatDate(inst, maxDate);
			this._attachments($(target), inst);
			this._autoSize(inst);
			this._setDateDatepicker(target, date);
			this._updateDatepicker(inst);
		}
	},

	// change method deprecated
	_changeDatepicker: function(target, name, value) {
		this._optionDatepicker(target, name, value);
	},

	/* Redraw the date picker attached to an input field or division.
	   @param  target  element - the target input field or division or span */
	_refreshDatepicker: function(target) {
		var inst = this._getInst(target);
		if (inst) {
			this._updateDatepicker(inst);
		}
	},

	/* Set the dates for a jQuery selection.
	   @param  target   element - the target input field or division or span
	   @param  date     Date - the new date */
	_setDateDatepicker: function(target, date) {
		var inst = this._getInst(target);
		if (inst) {
			this._setDate(inst, date);
			this._updateDatepicker(inst);
			this._updateAlternate(inst);
		}
	},

	/* Get the date(s) for the first entry in a jQuery selection.
	   @param  target     element - the target input field or division or span
	   @param  noDefault  boolean - true if no default date is to be used
	   @return Date - the current date */
	_getDateDatepicker: function(target, noDefault) {
		var inst = this._getInst(target);
		if (inst && !inst.inline)
			this._setDateFromField(inst, noDefault);
		return (inst ? this._getDate(inst) : null);
	},

	/* Handle keystrokes. */
	_doKeyDown: function(event) {
		var inst = $.datepicker._getInst(event.target);
		var handled = true;
		var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');
		inst._keyEvent = true;
		if ($.datepicker._datepickerShowing)
			switch (event.keyCode) {
				case 9: $.datepicker._hideDatepicker();
						handled = false;
						break; // hide on tab out
				case 13: var sel = $('td.' + $.datepicker._dayOverClass + ':not(.' + 
									$.datepicker._currentClass + ')', inst.dpDiv);
						if (sel[0])
							$.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
						else
							$.datepicker._hideDatepicker();
						return false; // don't submit the form
						break; // select the value on enter
				case 27: $.datepicker._hideDatepicker();
						break; // hide on escape
				case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
							-$.datepicker._get(inst, 'stepBigMonths') :
							-$.datepicker._get(inst, 'stepMonths')), 'M');
						break; // previous month/year on page up/+ ctrl
				case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
							+$.datepicker._get(inst, 'stepBigMonths') :
							+$.datepicker._get(inst, 'stepMonths')), 'M');
						break; // next month/year on page down/+ ctrl
				case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
						handled = event.ctrlKey || event.metaKey;
						break; // clear on ctrl or command +end
				case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
						handled = event.ctrlKey || event.metaKey;
						break; // current on ctrl or command +home
				case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
						handled = event.ctrlKey || event.metaKey;
						// -1 day on ctrl or command +left
						if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
									-$.datepicker._get(inst, 'stepBigMonths') :
									-$.datepicker._get(inst, 'stepMonths')), 'M');
						// next month/year on alt +left on Mac
						break;
				case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
						handled = event.ctrlKey || event.metaKey;
						break; // -1 week on ctrl or command +up
				case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
						handled = event.ctrlKey || event.metaKey;
						// +1 day on ctrl or command +right
						if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
									+$.datepicker._get(inst, 'stepBigMonths') :
									+$.datepicker._get(inst, 'stepMonths')), 'M');
						// next month/year on alt +right
						break;
				case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
						handled = event.ctrlKey || event.metaKey;
						break; // +1 week on ctrl or command +down
				default: handled = false;
			}
		else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
			$.datepicker._showDatepicker(this);
		else {
			handled = false;
		}
		if (handled) {
			event.preventDefault();
			event.stopPropagation();
		}
	},

	/* Filter entered characters - based on date format. */
	_doKeyPress: function(event) {
		var inst = $.datepicker._getInst(event.target);
		if ($.datepicker._get(inst, 'constrainInput')) {
			var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
			var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
			return event.ctrlKey || event.metaKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
		}
	},

	/* Synchronise manual entry and field/alternate field. */
	_doKeyUp: function(event) {
		var inst = $.datepicker._getInst(event.target);
		if (inst.input.val() != inst.lastVal) {
			try {
				var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
					(inst.input ? inst.input.val() : null),
					$.datepicker._getFormatConfig(inst));
				if (date) { // only if valid
					$.datepicker._setDateFromField(inst);
					$.datepicker._updateAlternate(inst);
					$.datepicker._updateDatepicker(inst);
				}
			}
			catch (event) {
				$.datepicker.log(event);
			}
		}
		return true;
	},

	/* Pop-up the date picker for a given input field.
	   @param  input  element - the input field attached to the date picker or
	                  event - if triggered by focus */
	_showDatepicker: function(input) {
		input = input.target || input;
		if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
			input = $('input', input.parentNode)[0];
		if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
			return;
		var inst = $.datepicker._getInst(input);
		if ($.datepicker._curInst && $.datepicker._curInst != inst) {
			$.datepicker._curInst.dpDiv.stop(true, true);
		}
		var beforeShow = $.datepicker._get(inst, 'beforeShow');
		extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {}));
		inst.lastVal = null;
		$.datepicker._lastInput = input;
		$.datepicker._setDateFromField(inst);
		if ($.datepicker._inDialog) // hide cursor
			input.value = '';
		if (!$.datepicker._pos) { // position below input
			$.datepicker._pos = $.datepicker._findPos(input);
			$.datepicker._pos[1] += input.offsetHeight; // add the height
		}
		var isFixed = false;
		$(input).parents().each(function() {
			isFixed |= $(this).css('position') == 'fixed';
			return !isFixed;
		});
		if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
			$.datepicker._pos[0] -= document.documentElement.scrollLeft;
			$.datepicker._pos[1] -= document.documentElement.scrollTop;
		}
		var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
		$.datepicker._pos = null;
		//to avoid flashes on Firefox
		inst.dpDiv.empty();
		// determine sizing offscreen
		inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
		$.datepicker._updateDatepicker(inst);
		// fix width for dynamic number of date pickers
		// and adjust position before showing
		offset = $.datepicker._checkOffset(inst, offset, isFixed);
		inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
			'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
			left: offset.left + 'px', top: offset.top + 'px'});
		if (!inst.inline) {
			var showAnim = $.datepicker._get(inst, 'showAnim');
			var duration = $.datepicker._get(inst, 'duration');
			var postProcess = function() {
				$.datepicker._datepickerShowing = true;
				var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only
				if( !! cover.length ){
					var borders = $.datepicker._getBorders(inst.dpDiv);
					cover.css({left: -borders[0], top: -borders[1],
						width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()});
				}
			};
			inst.dpDiv.zIndex($(input).zIndex()+1);
			if ($.effects && $.effects[showAnim])
				inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
			else
				inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess);
			if (!showAnim || !duration)
				postProcess();
			if (inst.input.is(':visible') && !inst.input.is(':disabled'))
				inst.input.focus();
			$.datepicker._curInst = inst;
		}
	},

	/* Generate the date picker content. */
	_updateDatepicker: function(inst) {
		var self = this;
		var borders = $.datepicker._getBorders(inst.dpDiv);
		inst.dpDiv.empty().append(this._generateHTML(inst));
		var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only
		if( !!cover.length ){ //avoid call to outerXXXX() when not in IE6
			cover.css({left: -borders[0], top: -borders[1], width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()})
		}
		inst.dpDiv.find('button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a')
				.bind('mouseout', function(){
					$(this).removeClass('ui-state-hover');
					if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover');
					if(this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover');
				})
				.bind('mouseover', function(){
					if (!self._isDisabledDatepicker( inst.inline ? inst.dpDiv.parent()[0] : inst.input[0])) {
						$(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
						$(this).addClass('ui-state-hover');
						if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover');
						if(this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover');
					}
				})
			.end()
			.find('.' + this._dayOverClass + ' a')
				.trigger('mouseover')
			.end();
		var numMonths = this._getNumberOfMonths(inst);
		var cols = numMonths[1];
		var width = 17;
		if (cols > 1)
			inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
		else
			inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
		inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
			'Class']('ui-datepicker-multi');
		inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
			'Class']('ui-datepicker-rtl');
		if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input &&
				// #6694 - don't focus the input if it's already focused
				// this breaks the change event in IE
				inst.input.is(':visible') && !inst.input.is(':disabled') && inst.input[0] != document.activeElement)
			inst.input.focus();
		// deffered render of the years select (to avoid flashes on Firefox) 
		if( inst.yearshtml ){
			var origyearshtml = inst.yearshtml;
			setTimeout(function(){
				//assure that inst.yearshtml didn't change.
				if( origyearshtml === inst.yearshtml ){
					inst.dpDiv.find('select.ui-datepicker-year:first').replaceWith(inst.yearshtml);
				}
				origyearshtml = inst.yearshtml = null;
			}, 0);
		}
	},

	/* Retrieve the size of left and top borders for an element.
	   @param  elem  (jQuery object) the element of interest
	   @return  (number[2]) the left and top borders */
	_getBorders: function(elem) {
		var convert = function(value) {
			return {thin: 1, medium: 2, thick: 3}[value] || value;
		};
		return [parseFloat(convert(elem.css('border-left-width'))),
			parseFloat(convert(elem.css('border-top-width')))];
	},

	/* Check positioning to remain on screen. */
	_checkOffset: function(inst, offset, isFixed) {
		var dpWidth = inst.dpDiv.outerWidth();
		var dpHeight = inst.dpDiv.outerHeight();
		var inputWidth = inst.input ? inst.input.outerWidth() : 0;
		var inputHeight = inst.input ? inst.input.outerHeight() : 0;
		var viewWidth = document.documentElement.clientWidth + $(document).scrollLeft();
		var viewHeight = document.documentElement.clientHeight + $(document).scrollTop();

		offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
		offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
		offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;

		// now check if datepicker is showing outside window viewport - move to a better place if so.
		offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
			Math.abs(offset.left + dpWidth - viewWidth) : 0);
		offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
			Math.abs(dpHeight + inputHeight) : 0);

		return offset;
	},

	/* Find an object's position on the screen. */
	_findPos: function(obj) {
		var inst = this._getInst(obj);
		var isRTL = this._get(inst, 'isRTL');
        while (obj && (obj.type == 'hidden' || obj.nodeType != 1 || $.expr.filters.hidden(obj))) {
            obj = obj[isRTL ? 'previousSibling' : 'nextSibling'];
        }
        var position = $(obj).offset();
	    return [position.left, position.top];
	},

	/* Hide the date picker from view.
	   @param  input  element - the input field attached to the date picker */
	_hideDatepicker: function(input) {
		var inst = this._curInst;
		if (!inst || (input && inst != $.data(input, PROP_NAME)))
			return;
		if (this._datepickerShowing) {
			var showAnim = this._get(inst, 'showAnim');
			var duration = this._get(inst, 'duration');
			var postProcess = function() {
				$.datepicker._tidyDialog(inst);
				this._curInst = null;
			};
			if ($.effects && $.effects[showAnim])
				inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
			else
				inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' :
					(showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);
			if (!showAnim)
				postProcess();
			var onClose = this._get(inst, 'onClose');
			if (onClose)
				onClose.apply((inst.input ? inst.input[0] : null),
					[(inst.input ? inst.input.val() : ''), inst]);  // trigger custom callback
			this._datepickerShowing = false;
			this._lastInput = null;
			if (this._inDialog) {
				this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
				if ($.blockUI) {
					$.unblockUI();
					$('body').append(this.dpDiv);
				}
			}
			this._inDialog = false;
		}
	},

	/* Tidy up after a dialog display. */
	_tidyDialog: function(inst) {
		inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
	},

	/* Close date picker if clicked elsewhere. */
	_checkExternalClick: function(event) {
		if (!$.datepicker._curInst)
			return;
		var $target = $(event.target);
		if ($target[0].id != $.datepicker._mainDivId &&
				$target.parents('#' + $.datepicker._mainDivId).length == 0 &&
				!$target.hasClass($.datepicker.markerClassName) &&
				!$target.hasClass($.datepicker._triggerClass) &&
				$.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI))
			$.datepicker._hideDatepicker();
	},

	/* Adjust one of the date sub-fields. */
	_adjustDate: function(id, offset, period) {
		var target = $(id);
		var inst = this._getInst(target[0]);
		if (this._isDisabledDatepicker(target[0])) {
			return;
		}
		this._adjustInstDate(inst, offset +
			(period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
			period);
		this._updateDatepicker(inst);
	},

	/* Action for current link. */
	_gotoToday: function(id) {
		var target = $(id);
		var inst = this._getInst(target[0]);
		if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
			inst.selectedDay = inst.currentDay;
			inst.drawMonth = inst.selectedMonth = inst.currentMonth;
			inst.drawYear = inst.selectedYear = inst.currentYear;
		}
		else {
			var date = new Date();
			inst.selectedDay = date.getDate();
			inst.drawMonth = inst.selectedMonth = date.getMonth();
			inst.drawYear = inst.selectedYear = date.getFullYear();
		}
		this._notifyChange(inst);
		this._adjustDate(target);
	},

	/* Action for selecting a new month/year. */
	_selectMonthYear: function(id, select, period) {
		var target = $(id);
		var inst = this._getInst(target[0]);
		inst._selectingMonthYear = false;
		inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
		inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
			parseInt(select.options[select.selectedIndex].value,10);
		this._notifyChange(inst);
		this._adjustDate(target);
	},

	/* Restore input focus after not changing month/year. */
	_clickMonthYear: function(id) {
		var target = $(id);
		var inst = this._getInst(target[0]);
		if (inst.input && inst._selectingMonthYear) {
			setTimeout(function() {
				inst.input.focus();
			}, 0);
		}
		inst._selectingMonthYear = !inst._selectingMonthYear;
	},

	/* Action for selecting a day. */
	_selectDay: function(id, month, year, td) {
		var target = $(id);
		if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
			return;
		}
		var inst = this._getInst(target[0]);
		inst.selectedDay = inst.currentDay = $('a', td).html();
		inst.selectedMonth = inst.currentMonth = month;
		inst.selectedYear = inst.currentYear = year;
		this._selectDate(id, this._formatDate(inst,
			inst.currentDay, inst.currentMonth, inst.currentYear));
	},

	/* Erase the input field and hide the date picker. */
	_clearDate: function(id) {
		var target = $(id);
		var inst = this._getInst(target[0]);
		this._selectDate(target, '');
	},

	/* Update the input field with the selected date. */
	_selectDate: function(id, dateStr) {
		var target = $(id);
		var inst = this._getInst(target[0]);
		dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
		if (inst.input)
			inst.input.val(dateStr);
		this._updateAlternate(inst);
		var onSelect = this._get(inst, 'onSelect');
		if (onSelect)
			onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);  // trigger custom callback
		else if (inst.input)
			inst.input.trigger('change'); // fire the change event
		if (inst.inline)
			this._updateDatepicker(inst);
		else {
			this._hideDatepicker();
			this._lastInput = inst.input[0];
			if (typeof(inst.input[0]) != 'object')
				inst.input.focus(); // restore focus
			this._lastInput = null;
		}
	},

	/* Update any alternate field to synchronise with the main field. */
	_updateAlternate: function(inst) {
		var altField = this._get(inst, 'altField');
		if (altField) { // update alternate field too
			var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
			var date = this._getDate(inst);
			var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
			$(altField).each(function() { $(this).val(dateStr); });
		}
	},

	/* Set as beforeShowDay function to prevent selection of weekends.
	   @param  date  Date - the date to customise
	   @return [boolean, string] - is this date selectable?, what is its CSS class? */
	noWeekends: function(date) {
		var day = date.getDay();
		return [(day > 0 && day < 6), ''];
	},

	/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
	   @param  date  Date - the date to get the week for
	   @return  number - the number of the week within the year that contains this date */
	iso8601Week: function(date) {
		var checkDate = new Date(date.getTime());
		// Find Thursday of this week starting on Monday
		checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
		var time = checkDate.getTime();
		checkDate.setMonth(0); // Compare with Jan 1
		checkDate.setDate(1);
		return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
	},

	/* Parse a string value into a date object.
	   See formatDate below for the possible formats.

	   @param  format    string - the expected format of the date
	   @param  value     string - the date in the above format
	   @param  settings  Object - attributes include:
	                     shortYearCutoff  number - the cutoff year for determining the century (optional)
	                     dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
	                     dayNames         string[7] - names of the days from Sunday (optional)
	                     monthNamesShort  string[12] - abbreviated names of the months (optional)
	                     monthNames       string[12] - names of the months (optional)
	   @return  Date - the extracted date value or null if value is blank */
	parseDate: function (format, value, settings) {
		if (format == null || value == null)
			throw 'Invalid arguments';
		value = (typeof value == 'object' ? value.toString() : value + '');
		if (value == '')
			return null;
		var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
		shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
				new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
		var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
		var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
		var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
		var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
		var year = -1;
		var month = -1;
		var day = -1;
		var doy = -1;
		var literal = false;
		// Check whether a format character is doubled
		var lookAhead = function(match) {
			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
			if (matches)
				iFormat++;
			return matches;
		};
		// Extract a number from the string value
		var getNumber = function(match) {
			var isDoubled = lookAhead(match);
			var size = (match == '@' ? 14 : (match == '!' ? 20 :
				(match == 'y' && isDoubled ? 4 : (match == 'o' ? 3 : 2))));
			var digits = new RegExp('^\\d{1,' + size + '}');
			var num = value.substring(iValue).match(digits);
			if (!num)
				throw 'Missing number at position ' + iValue;
			iValue += num[0].length;
			return parseInt(num[0], 10);
		};
		// Extract a name from the string value and convert to an index
		var getName = function(match, shortNames, longNames) {
			var names = (lookAhead(match) ? longNames : shortNames);
			for (var i = 0; i < names.length; i++) {
				if (value.substr(iValue, names[i].length).toLowerCase() == names[i].toLowerCase()) {
					iValue += names[i].length;
					return i + 1;
				}
			}
			throw 'Unknown name at position ' + iValue;
		};
		// Confirm that a literal character matches the string value
		var checkLiteral = function() {
			if (value.charAt(iValue) != format.charAt(iFormat))
				throw 'Unexpected literal at position ' + iValue;
			iValue++;
		};
		var iValue = 0;
		for (var iFormat = 0; iFormat < format.length; iFormat++) {
			if (literal)
				if (format.charAt(iFormat) == "'" && !lookAhead("'"))
					literal = false;
				else
					checkLiteral();
			else
				switch (format.charAt(iFormat)) {
					case 'd':
						day = getNumber('d');
						break;
					case 'D':
						getName('D', dayNamesShort, dayNames);
						break;
					case 'o':
						doy = getNumber('o');
						break;
					case 'm':
						month = getNumber('m');
						break;
					case 'M':
						month = getName('M', monthNamesShort, monthNames);
						break;
					case 'y':
						year = getNumber('y');
						break;
					case '@':
						var date = new Date(getNumber('@'));
						year = date.getFullYear();
						month = date.getMonth() + 1;
						day = date.getDate();
						break;
					case '!':
						var date = new Date((getNumber('!') - this._ticksTo1970) / 10000);
						year = date.getFullYear();
						month = date.getMonth() + 1;
						day = date.getDate();
						break;
					case "'":
						if (lookAhead("'"))
							checkLiteral();
						else
							literal = true;
						break;
					default:
						checkLiteral();
				}
		}
		if (year == -1)
			year = new Date().getFullYear();
		else if (year < 100)
			year += new Date().getFullYear() - new Date().getFullYear() % 100 +
				(year <= shortYearCutoff ? 0 : -100);
		if (doy > -1) {
			month = 1;
			day = doy;
			do {
				var dim = this._getDaysInMonth(year, month - 1);
				if (day <= dim)
					break;
				month++;
				day -= dim;
			} while (true);
		}
		var date = this._daylightSavingAdjust(new Date(year, month - 1, day));
		if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
			throw 'Invalid date'; // E.g. 31/02/*
		return date;
	},

	/* Standard date formats. */
	ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
	COOKIE: 'D, dd M yy',
	ISO_8601: 'yy-mm-dd',
	RFC_822: 'D, d M y',
	RFC_850: 'DD, dd-M-y',
	RFC_1036: 'D, d M y',
	RFC_1123: 'D, d M yy',
	RFC_2822: 'D, d M yy',
	RSS: 'D, d M y', // RFC 822
	TICKS: '!',
	TIMESTAMP: '@',
	W3C: 'yy-mm-dd', // ISO 8601

	_ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
		Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),

	/* Format a date object into a string value.
	   The format can be combinations of the following:
	   d  - day of month (no leading zero)
	   dd - day of month (two digit)
	   o  - day of year (no leading zeros)
	   oo - day of year (three digit)
	   D  - day name short
	   DD - day name long
	   m  - month of year (no leading zero)
	   mm - month of year (two digit)
	   M  - month name short
	   MM - month name long
	   y  - year (two digit)
	   yy - year (four digit)
	   @ - Unix timestamp (ms since 01/01/1970)
	   ! - Windows ticks (100ns since 01/01/0001)
	   '...' - literal text
	   '' - single quote

	   @param  format    string - the desired format of the date
	   @param  date      Date - the date value to format
	   @param  settings  Object - attributes include:
	                     dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
	                     dayNames         string[7] - names of the days from Sunday (optional)
	                     monthNamesShort  string[12] - abbreviated names of the months (optional)
	                     monthNames       string[12] - names of the months (optional)
	   @return  string - the date in the above format */
	formatDate: function (format, date, settings) {
		if (!date)
			return '';
		var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
		var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
		var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
		var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
		// Check whether a format character is doubled
		var lookAhead = function(match) {
			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
			if (matches)
				iFormat++;
			return matches;
		};
		// Format a number, with leading zero if necessary
		var formatNumber = function(match, value, len) {
			var num = '' + value;
			if (lookAhead(match))
				while (num.length < len)
					num = '0' + num;
			return num;
		};
		// Format a name, short or long as requested
		var formatName = function(match, value, shortNames, longNames) {
			return (lookAhead(match) ? longNames[value] : shortNames[value]);
		};
		var output = '';
		var literal = false;
		if (date)
			for (var iFormat = 0; iFormat < format.length; iFormat++) {
				if (literal)
					if (format.charAt(iFormat) == "'" && !lookAhead("'"))
						literal = false;
					else
						output += format.charAt(iFormat);
				else
					switch (format.charAt(iFormat)) {
						case 'd':
							output += formatNumber('d', date.getDate(), 2);
							break;
						case 'D':
							output += formatName('D', date.getDay(), dayNamesShort, dayNames);
							break;
						case 'o':
							output += formatNumber('o',
								(date.getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000, 3);
							break;
						case 'm':
							output += formatNumber('m', date.getMonth() + 1, 2);
							break;
						case 'M':
							output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
							break;
						case 'y':
							output += (lookAhead('y') ? date.getFullYear() :
								(date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
							break;
						case '@':
							output += date.getTime();
							break;
						case '!':
							output += date.getTime() * 10000 + this._ticksTo1970;
							break;
						case "'":
							if (lookAhead("'"))
								output += "'";
							else
								literal = true;
							break;
						default:
							output += format.charAt(iFormat);
					}
			}
		return output;
	},

	/* Extract all possible characters from the date format. */
	_possibleChars: function (format) {
		var chars = '';
		var literal = false;
		// Check whether a format character is doubled
		var lookAhead = function(match) {
			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
			if (matches)
				iFormat++;
			return matches;
		};
		for (var iFormat = 0; iFormat < format.length; iFormat++)
			if (literal)
				if (format.charAt(iFormat) == "'" && !lookAhead("'"))
					literal = false;
				else
					chars += format.charAt(iFormat);
			else
				switch (format.charAt(iFormat)) {
					case 'd': case 'm': case 'y': case '@':
						chars += '0123456789';
						break;
					case 'D': case 'M':
						return null; // Accept anything
					case "'":
						if (lookAhead("'"))
							chars += "'";
						else
							literal = true;
						break;
					default:
						chars += format.charAt(iFormat);
				}
		return chars;
	},

	/* Get a setting value, defaulting if necessary. */
	_get: function(inst, name) {
		return inst.settings[name] !== undefined ?
			inst.settings[name] : this._defaults[name];
	},

	/* Parse existing date and initialise date picker. */
	_setDateFromField: function(inst, noDefault) {
		if (inst.input.val() == inst.lastVal) {
			return;
		}
		var dateFormat = this._get(inst, 'dateFormat');
		var dates = inst.lastVal = inst.input ? inst.input.val() : null;
		var date, defaultDate;
		date = defaultDate = this._getDefaultDate(inst);
		var settings = this._getFormatConfig(inst);
		try {
			date = this.parseDate(dateFormat, dates, settings) || defaultDate;
		} catch (event) {
			this.log(event);
			dates = (noDefault ? '' : dates);
		}
		inst.selectedDay = date.getDate();
		inst.drawMonth = inst.selectedMonth = date.getMonth();
		inst.drawYear = inst.selectedYear = date.getFullYear();
		inst.currentDay = (dates ? date.getDate() : 0);
		inst.currentMonth = (dates ? date.getMonth() : 0);
		inst.currentYear = (dates ? date.getFullYear() : 0);
		this._adjustInstDate(inst);
	},

	/* Retrieve the default date shown on opening. */
	_getDefaultDate: function(inst) {
		return this._restrictMinMax(inst,
			this._determineDate(inst, this._get(inst, 'defaultDate'), new Date()));
	},

	/* A date may be specified as an exact value or a relative one. */
	_determineDate: function(inst, date, defaultDate) {
		var offsetNumeric = function(offset) {
			var date = new Date();
			date.setDate(date.getDate() + offset);
			return date;
		};
		var offsetString = function(offset) {
			try {
				return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
					offset, $.datepicker._getFormatConfig(inst));
			}
			catch (e) {
				// Ignore
			}
			var date = (offset.toLowerCase().match(/^c/) ?
				$.datepicker._getDate(inst) : null) || new Date();
			var year = date.getFullYear();
			var month = date.getMonth();
			var day = date.getDate();
			var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
			var matches = pattern.exec(offset);
			while (matches) {
				switch (matches[2] || 'd') {
					case 'd' : case 'D' :
						day += parseInt(matches[1],10); break;
					case 'w' : case 'W' :
						day += parseInt(matches[1],10) * 7; break;
					case 'm' : case 'M' :
						month += parseInt(matches[1],10);
						day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
						break;
					case 'y': case 'Y' :
						year += parseInt(matches[1],10);
						day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
						break;
				}
				matches = pattern.exec(offset);
			}
			return new Date(year, month, day);
		};
		var newDate = (date == null || date === '' ? defaultDate : (typeof date == 'string' ? offsetString(date) :
			(typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));
		newDate = (newDate && newDate.toString() == 'Invalid Date' ? defaultDate : newDate);
		if (newDate) {
			newDate.setHours(0);
			newDate.setMinutes(0);
			newDate.setSeconds(0);
			newDate.setMilliseconds(0);
		}
		return this._daylightSavingAdjust(newDate);
	},

	/* Handle switch to/from daylight saving.
	   Hours may be non-zero on daylight saving cut-over:
	   > 12 when midnight changeover, but then cannot generate
	   midnight datetime, so jump to 1AM, otherwise reset.
	   @param  date  (Date) the date to check
	   @return  (Date) the corrected date */
	_daylightSavingAdjust: function(date) {
		if (!date) return null;
		date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
		return date;
	},

	/* Set the date(s) directly. */
	_setDate: function(inst, date, noChange) {
		var clear = !date;
		var origMonth = inst.selectedMonth;
		var origYear = inst.selectedYear;
		var newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
		inst.selectedDay = inst.currentDay = newDate.getDate();
		inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
		inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
		if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange)
			this._notifyChange(inst);
		this._adjustInstDate(inst);
		if (inst.input) {
			inst.input.val(clear ? '' : this._formatDate(inst));
		}
	},

	/* Retrieve the date(s) directly. */
	_getDate: function(inst) {
		var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
			this._daylightSavingAdjust(new Date(
			inst.currentYear, inst.currentMonth, inst.currentDay)));
			return startDate;
	},

	/* Generate the HTML for the current state of the date picker. */
	_generateHTML: function(inst) {
		var today = new Date();
		today = this._daylightSavingAdjust(
			new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time
		var isRTL = this._get(inst, 'isRTL');
		var showButtonPanel = this._get(inst, 'showButtonPanel');
		var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
		var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
		var numMonths = this._getNumberOfMonths(inst);
		var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
		var stepMonths = this._get(inst, 'stepMonths');
		var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
		var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
			new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
		var minDate = this._getMinMaxDate(inst, 'min');
		var maxDate = this._getMinMaxDate(inst, 'max');
		var drawMonth = inst.drawMonth - showCurrentAtPos;
		var drawYear = inst.drawYear;
		if (drawMonth < 0) {
			drawMonth += 12;
			drawYear--;
		}
		if (maxDate) {
			var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
				maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
			maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
			while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
				drawMonth--;
				if (drawMonth < 0) {
					drawMonth = 11;
					drawYear--;
				}
			}
		}
		inst.drawMonth = drawMonth;
		inst.drawYear = drawYear;
		var prevText = this._get(inst, 'prevText');
		prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
			this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
			this._getFormatConfig(inst)));
		var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
			'<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_' + dpuuid +
			'.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
			' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
			(hideIfNoPrevNext ? '' : '<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+ prevText +'"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>'));
		var nextText = this._get(inst, 'nextText');
		nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
			this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
			this._getFormatConfig(inst)));
		var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
			'<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_' + dpuuid +
			'.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
			' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
			(hideIfNoPrevNext ? '' : '<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+ nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>'));
		var currentText = this._get(inst, 'currentText');
		var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
		currentText = (!navigationAsDateFormat ? currentText :
			this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
		var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
			'.datepicker._hideDatepicker();">' + this._get(inst, 'closeText') + '</button>' : '');
		var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
			(this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
			'.datepicker._gotoToday(\'#' + inst.id + '\');"' +
			'>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
		var firstDay = parseInt(this._get(inst, 'firstDay'),10);
		firstDay = (isNaN(firstDay) ? 0 : firstDay);
		var showWeek = this._get(inst, 'showWeek');
		var dayNames = this._get(inst, 'dayNames');
		var dayNamesShort = this._get(inst, 'dayNamesShort');
		var dayNamesMin = this._get(inst, 'dayNamesMin');
		var monthNames = this._get(inst, 'monthNames');
		var monthNamesShort = this._get(inst, 'monthNamesShort');
		var beforeShowDay = this._get(inst, 'beforeShowDay');
		var showOtherMonths = this._get(inst, 'showOtherMonths');
		var selectOtherMonths = this._get(inst, 'selectOtherMonths');
		var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
		var defaultDate = this._getDefaultDate(inst);
		var html = '';
		for (var row = 0; row < numMonths[0]; row++) {
			var group = '';
			for (var col = 0; col < numMonths[1]; col++) {
				var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
				var cornerClass = ' ui-corner-all';
				var calender = '';
				if (isMultiMonth) {
					calender += '<div class="ui-datepicker-group';
					if (numMonths[1] > 1)
						switch (col) {
							case 0: calender += ' ui-datepicker-group-first';
								cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
							case numMonths[1]-1: calender += ' ui-datepicker-group-last';
								cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
							default: calender += ' ui-datepicker-group-middle'; cornerClass = ''; break;
						}
					calender += '">';
				}
				calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
					(/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
					(/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
					this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
					row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
					'</div><table class="ui-datepicker-calendar"><thead>' +
					'<tr>';
				var thead = (showWeek ? '<th class="ui-datepicker-week-col">' + this._get(inst, 'weekHeader') + '</th>' : '');
				for (var dow = 0; dow < 7; dow++) { // days of the week
					var day = (dow + firstDay) % 7;
					thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
						'<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
				}
				calender += thead + '</tr></thead><tbody>';
				var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
				if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
					inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
				var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
				var numRows = (isMultiMonth ? 6 : Math.ceil((leadDays + daysInMonth) / 7)); // calculate the number of rows to generate
				var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
				for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
					calender += '<tr>';
					var tbody = (!showWeek ? '' : '<td class="ui-datepicker-week-col">' +
						this._get(inst, 'calculateWeek')(printDate) + '</td>');
					for (var dow = 0; dow < 7; dow++) { // create date picker days
						var daySettings = (beforeShowDay ?
							beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
						var otherMonth = (printDate.getMonth() != drawMonth);
						var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
							(minDate && printDate < minDate) || (maxDate && printDate > maxDate);
						tbody += '<td class="' +
							((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
							(otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
							((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
							(defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
							// or defaultDate is current printedDate and defaultDate is selectedDate
							' ' + this._dayOverClass : '') + // highlight selected day
							(unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') +  // highlight unselectable days
							(otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
							(printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day
							(printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
							((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
							(unselectable ? '' : ' onclick="DP_jQuery_' + dpuuid + '.datepicker._selectDay(\'#' +
							inst.id + '\',' + printDate.getMonth() + ',' + printDate.getFullYear() + ', this);return false;"') + '>' + // actions
							(otherMonth && !showOtherMonths ? '&#xa0;' : // display for other months
							(unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
							(printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
							(printDate.getTime() == currentDate.getTime() ? ' ui-state-active' : '') + // highlight selected day
							(otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months
							'" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date
						printDate.setDate(printDate.getDate() + 1);
						printDate = this._daylightSavingAdjust(printDate);
					}
					calender += tbody + '</tr>';
				}
				drawMonth++;
				if (drawMonth > 11) {
					drawMonth = 0;
					drawYear++;
				}
				calender += '</tbody></table>' + (isMultiMonth ? '</div>' + 
							((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
				group += calender;
			}
			html += group;
		}
		html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ?
			'<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
		inst._keyEvent = false;
		return html;
	},

	/* Generate the month and year header. */
	_generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
			secondary, monthNames, monthNamesShort) {
		var changeMonth = this._get(inst, 'changeMonth');
		var changeYear = this._get(inst, 'changeYear');
		var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
		var html = '<div class="ui-datepicker-title">';
		var monthHtml = '';
		// month selection
		if (secondary || !changeMonth)
			monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span>';
		else {
			var inMinYear = (minDate && minDate.getFullYear() == drawYear);
			var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
			monthHtml += '<select class="ui-datepicker-month" ' +
				'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +
				'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
			 	'>';
			for (var month = 0; month < 12; month++) {
				if ((!inMinYear || month >= minDate.getMonth()) &&
						(!inMaxYear || month <= maxDate.getMonth()))
					monthHtml += '<option value="' + month + '"' +
						(month == drawMonth ? ' selected="selected"' : '') +
						'>' + monthNamesShort[month] + '</option>';
			}
			monthHtml += '</select>';
		}
		if (!showMonthAfterYear)
			html += monthHtml + (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '');
		// year selection
		inst.yearshtml = '';
		if (secondary || !changeYear)
			html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
		else {
			// determine range of years to display
			var years = this._get(inst, 'yearRange').split(':');
			var thisYear = new Date().getFullYear();
			var determineYear = function(value) {
				var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) :
					(value.match(/[+-].*/) ? thisYear + parseInt(value, 10) :
					parseInt(value, 10)));
				return (isNaN(year) ? thisYear : year);
			};
			var year = determineYear(years[0]);
			var endYear = Math.max(year, determineYear(years[1] || ''));
			year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
			endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
			inst.yearshtml += '<select class="ui-datepicker-year" ' +
				'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +
				'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
				'>';
			for (; year <= endYear; year++) {
				inst.yearshtml += '<option value="' + year + '"' +
					(year == drawYear ? ' selected="selected"' : '') +
					'>' + year + '</option>';
			}
			inst.yearshtml += '</select>';
			//when showing there is no need for later update
			if( ! $.browser.mozilla ){
				html += inst.yearshtml;
				inst.yearshtml = null;
			} else {
				// will be replaced later with inst.yearshtml
				html += '<select class="ui-datepicker-year"><option value="' + drawYear + '" selected="selected">' + drawYear + '</option></select>';
			}
		}
		html += this._get(inst, 'yearSuffix');
		if (showMonthAfterYear)
			html += (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '') + monthHtml;
		html += '</div>'; // Close datepicker_header
		return html;
	},

	/* Adjust one of the date sub-fields. */
	_adjustInstDate: function(inst, offset, period) {
		var year = inst.drawYear + (period == 'Y' ? offset : 0);
		var month = inst.drawMonth + (period == 'M' ? offset : 0);
		var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
			(period == 'D' ? offset : 0);
		var date = this._restrictMinMax(inst,
			this._daylightSavingAdjust(new Date(year, month, day)));
		inst.selectedDay = date.getDate();
		inst.drawMonth = inst.selectedMonth = date.getMonth();
		inst.drawYear = inst.selectedYear = date.getFullYear();
		if (period == 'M' || period == 'Y')
			this._notifyChange(inst);
	},

	/* Ensure a date is within any min/max bounds. */
	_restrictMinMax: function(inst, date) {
		var minDate = this._getMinMaxDate(inst, 'min');
		var maxDate = this._getMinMaxDate(inst, 'max');
		var newDate = (minDate && date < minDate ? minDate : date);
		newDate = (maxDate && newDate > maxDate ? maxDate : newDate);
		return newDate;
	},

	/* Notify change of month/year. */
	_notifyChange: function(inst) {
		var onChange = this._get(inst, 'onChangeMonthYear');
		if (onChange)
			onChange.apply((inst.input ? inst.input[0] : null),
				[inst.selectedYear, inst.selectedMonth + 1, inst]);
	},

	/* Determine the number of months to show. */
	_getNumberOfMonths: function(inst) {
		var numMonths = this._get(inst, 'numberOfMonths');
		return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
	},

	/* Determine the current maximum date - ensure no time components are set. */
	_getMinMaxDate: function(inst, minMax) {
		return this._determineDate(inst, this._get(inst, minMax + 'Date'), null);
	},

	/* Find the number of days in a given month. */
	_getDaysInMonth: function(year, month) {
		return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();
	},

	/* Find the day of the week of the first of a month. */
	_getFirstDayOfMonth: function(year, month) {
		return new Date(year, month, 1).getDay();
	},

	/* Determines if we should allow a "next/prev" month display change. */
	_canAdjustMonth: function(inst, offset, curYear, curMonth) {
		var numMonths = this._getNumberOfMonths(inst);
		var date = this._daylightSavingAdjust(new Date(curYear,
			curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
		if (offset < 0)
			date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
		return this._isInRange(inst, date);
	},

	/* Is the given date in the accepted range? */
	_isInRange: function(inst, date) {
		var minDate = this._getMinMaxDate(inst, 'min');
		var maxDate = this._getMinMaxDate(inst, 'max');
		return ((!minDate || date.getTime() >= minDate.getTime()) &&
			(!maxDate || date.getTime() <= maxDate.getTime()));
	},

	/* Provide the configuration settings for formatting/parsing. */
	_getFormatConfig: function(inst) {
		var shortYearCutoff = this._get(inst, 'shortYearCutoff');
		shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
			new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
		return {shortYearCutoff: shortYearCutoff,
			dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
			monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
	},

	/* Format the given date for display. */
	_formatDate: function(inst, day, month, year) {
		if (!day) {
			inst.currentDay = inst.selectedDay;
			inst.currentMonth = inst.selectedMonth;
			inst.currentYear = inst.selectedYear;
		}
		var date = (day ? (typeof day == 'object' ? day :
			this._daylightSavingAdjust(new Date(year, month, day))) :
			this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
		return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
	}
});

/* jQuery extend now ignores nulls! */
function extendRemove(target, props) {
	$.extend(target, props);
	for (var name in props)
		if (props[name] == null || props[name] == undefined)
			target[name] = props[name];
	return target;
};

/* Determine whether an object is an array. */
function isArray(a) {
	return (a && (($.browser.safari && typeof a == 'object' && a.length) ||
		(a.constructor && a.constructor.toString().match(/\Array\(\)/))));
};

/* Invoke the datepicker functionality.
   @param  options  string - a command, optionally followed by additional parameters or
                    Object - settings for attaching new datepicker functionality
   @return  jQuery object */
$.fn.datepicker = function(options){
	
	/* Verify an empty collection wasn't passed - Fixes #6976 */
	if ( !this.length ) {
		return this;
	}
	
	/* Initialise the date picker. */
	if (!$.datepicker.initialized) {
		$(document).mousedown($.datepicker._checkExternalClick).
			find('body').append($.datepicker.dpDiv);
		$.datepicker.initialized = true;
	}

	var otherArgs = Array.prototype.slice.call(arguments, 1);
	if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget'))
		return $.datepicker['_' + options + 'Datepicker'].
			apply($.datepicker, [this[0]].concat(otherArgs));
	if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
		return $.datepicker['_' + options + 'Datepicker'].
			apply($.datepicker, [this[0]].concat(otherArgs));
	return this.each(function() {
		typeof options == 'string' ?
			$.datepicker['_' + options + 'Datepicker'].
				apply($.datepicker, [this].concat(otherArgs)) :
			$.datepicker._attachDatepicker(this, options);
	});
};

$.datepicker = new Datepicker(); // singleton instance
$.datepicker.initialized = false;
$.datepicker.uuid = new Date().getTime();
$.datepicker.version = "1.8.11";

// Workaround for #4055
// Add another global to avoid noConflict issues with inline event handlers
window['DP_jQuery_' + dpuuid] = $;

})(jQuery);


/*!
 * jScrollPane - v2.0.0beta5 - 2010-09-18
 * http://jscrollpane.kelvinluck.com/
 *
 * Copyright (c) 2010 Kelvin Luck
 * Dual licensed under the MIT and GPL licenses.
 */

// Script: jScrollPane - cross browser customisable scrollbars
//
// *Version: 2.0.0beta5, Last updated: 2010-09-18*
//
// Project Home - http://jscrollpane.kelvinluck.com/
// GitHub       - http://github.com/vitch/jScrollPane
// Source       - http://github.com/vitch/jScrollPane/raw/master/script/jquery.jscrollpane.js
// (Minified)   - http://github.com/vitch/jScrollPane/raw/master/script/jquery.jscrollpane.min.js
//
// About: License
//
// Copyright (c) 2010 Kelvin Luck
// Dual licensed under the MIT or GPL Version 2 licenses.
// http://jscrollpane.kelvinluck.com/MIT-LICENSE.txt
// http://jscrollpane.kelvinluck.com/GPL-LICENSE.txt
//
// About: Examples
//
// All examples and demos are available through the jScrollPane example site at:
// http://jscrollpane.kelvinluck.com/
//
// About: Support and Testing
//
// This plugin is tested on the browsers below and has been found to work reliably on them. If you run
// into a problem on one of the supported browsers then please visit the support section on the jScrollPane
// website (http://jscrollpane.kelvinluck.com/) for more information on getting support. You are also
// welcome to fork the project on GitHub if you can contribute a fix for a given issue. 
//
// jQuery Versions - 1.4.2
// Browsers Tested - Firefox 3.6.8, Safari 5, Opera 10.6, Chrome 5.0, IE 6, 7, 8
//
// About: Release History
//
// 2.0.0beta5 - (in progess)
// 2.0.0beta4 - (2010-09-17) clickOnTrack support, bug fixes
// 2.0.0beta3 - (2010-08-27) Horizontal mousewheel, mwheelIntent, keyboard support, bug fixes
// 2.0.0beta2 - (2010-08-21) Bug fixes
// 2.0.0beta1 - (2010-08-17) Rewrite to follow modern best practices and enable horizontal scrolling, initially hidden
//							 elements and dynamically sized elements.
// 1.x - (2006-12-31 - 2010-07-31) Initial version, hosted at googlecode, deprecated

(function($,window,undefined){

	$.fn.jScrollPane = function(settings)
	{
		// JScrollPane "class" - public methods are available through $('selector').data('jsp')
		function JScrollPane(elem, s)
		{

			var settings, jsp = this, pane, paneWidth, paneHeight, container, contentWidth, contentHeight,
				percentInViewH, percentInViewV, isScrollableV, isScrollableH, verticalDrag, dragMaxY,
				verticalDragPosition, horizontalDrag, dragMaxX, horizontalDragPosition,
				verticalBar, verticalTrack, scrollbarWidth, verticalTrackHeight, verticalDragHeight, arrowUp, arrowDown,
				horizontalBar, horizontalTrack, horizontalTrackWidth, horizontalDragWidth, arrowLeft, arrowRight,
				reinitialiseInterval, originalPadding, originalPaddingTotalWidth, previousPaneWidth,
				wasAtTop = true, wasAtLeft = true, wasAtBottom = false, wasAtRight = false,
				mwEvent = $.fn.mwheelIntent ? 'mwheelIntent.jsp' : 'mousewheel.jsp';

			originalPadding = elem.css('paddingTop') + ' ' +
								elem.css('paddingRight') + ' ' +
								elem.css('paddingBottom') + ' ' +
								elem.css('paddingLeft');
			originalPaddingTotalWidth = (parseInt(elem.css('paddingLeft')) || 0) +
										(parseInt(elem.css('paddingRight')) || 0);

			initialise(s);

			function initialise(s)
			{

				var clonedElem, tempWrapper, /*firstChild, lastChild, */isMaintainingPositon, lastContentX, lastContentY,
						hasContainingSpaceChanged;

				settings = s;

				if (pane == undefined) {

					elem.css(
						{
							'overflow': 'hidden',
							'padding': 0
						}
					);
					// TODO: Deal with where width/ height is 0 as it probably means the element is hidden and we should
					// come back to it later and check once it is unhidden...
					paneWidth = elem.innerWidth() + originalPaddingTotalWidth;
					paneHeight = elem.innerHeight();

					elem.width(paneWidth);
					
					pane = $('<div class="jspPane" />').wrap(
						$('<div class="jspContainer" />')
							.css({
								'width': paneWidth + 'px',
								'height': paneHeight + 'px'
							}
						)
					);

					elem.wrapInner(pane.parent());
					// Need to get the vars after being added to the document, otherwise they reference weird
					// disconnected orphan elements...
					container = elem.find('>.jspContainer');
					pane = container.find('>.jspPane');
					pane.css('padding', originalPadding);

					/*
					// Move any margins from the first and last children up to the container so they can still
					// collapse with neighbouring elements as they would before jScrollPane 
					firstChild = pane.find(':first-child');
					lastChild = pane.find(':last-child');
					elem.css(
						{
							'margin-top': firstChild.css('margin-top'),
							'margin-bottom': lastChild.css('margin-bottom')
						}
					);
					firstChild.css('margin-top', 0);
					lastChild.css('margin-bottom', 0);
					*/
				} else {

					elem.css('width', null);

					hasContainingSpaceChanged = elem.outerWidth() + originalPaddingTotalWidth != paneWidth || elem.outerHeight() != paneHeight;

					if (hasContainingSpaceChanged) {
						paneWidth = elem.innerWidth() + originalPaddingTotalWidth;
						paneHeight = elem.innerHeight();
						container.css({
							'width': paneWidth + 'px',
							'height': paneHeight + 'px'
						});
					}

					previousPaneWidth = pane.innerWidth();

					if (!hasContainingSpaceChanged && pane.outerWidth() == contentWidth && pane.outerHeight() == contentHeight) {
						// Nothing has changed since we last initialised
						if (isScrollableH || isScrollableV) { // If we had already set a width then re-set it
							pane.css('width', previousPaneWidth + 'px');
							elem.css('width', (previousPaneWidth + originalPaddingTotalWidth) + 'px');
						}
						// Then abort...
						return;
					}
					
					pane.css('width', null);
					elem.css('width', (paneWidth ) + 'px');

					container.find('>.jspVerticalBar,>.jspHorizontalBar').remove().end();
				}

				// Unfortunately it isn't that easy to find out the width of the element as it will always report the
				// width as allowed by its container, regardless of overflow settings.
				// A cunning workaround is to clone the element, set its position to absolute and place it in a narrow
				// container. Now it will push outwards to its maxium real width...
				clonedElem = pane.clone().css('position', 'absolute');
				tempWrapper = $('<div style="width:1px; position: relative;" />').append(clonedElem);
				$('body').append(tempWrapper);
				contentWidth = Math.max(pane.outerWidth(), clonedElem.outerWidth());
				tempWrapper.remove();
				
				contentHeight = pane.outerHeight();
				percentInViewH = contentWidth / paneWidth;
				percentInViewV = contentHeight / paneHeight;
				isScrollableV = percentInViewV > 1;

				isScrollableH = percentInViewH > 1;

				//console.log(paneWidth, paneHeight, contentWidth, contentHeight, percentInViewH, percentInViewV, isScrollableH, isScrollableV);

				if (!(isScrollableH || isScrollableV)) {
					elem.removeClass('jspScrollable');
					pane.css({
						'top': 0,
						'width': container.width() - originalPaddingTotalWidth
					});
					removeMousewheel();
					removeFocusHandler();
					removeKeyboardNav();
					removeClickOnTrack();
					unhijackInternalLinks();
				} else {
					elem.addClass('jspScrollable');

					isMaintainingPositon = settings.maintainPosition && (verticalDragPosition || horizontalDragPosition);
					if (isMaintainingPositon) {
						lastContentX = contentPositionX();
						lastContentY = contentPositionY();
					}

					initialiseVerticalScroll();
					initialiseHorizontalScroll();
					resizeScrollbars();

					if (isMaintainingPositon) {
						scrollToX(lastContentX);
						scrollToY(lastContentY);
					}

					initFocusHandler();
					initMousewheel();
					if (settings.enableKeyboardNavigation) {
						initKeyboardNav();
					}
					if (settings.clickOnTrack) {
						initClickOnTrack();
					}
					
					observeHash();
					if (settings.hijackInternalLinks) {
						hijackInternalLinks();
					}
				}

				if (settings.autoReinitialise && !reinitialiseInterval) {
					reinitialiseInterval = setInterval(
						function()
						{
							initialise(settings);
						},
						settings.autoReinitialiseDelay
					);
				} else if (!settings.autoReinitialise && reinitialiseInterval) {
					clearInterval(reinitialiseInterval)
				}

				elem.trigger('jsp-initialised', [isScrollableH || isScrollableV]);
			}

			function initialiseVerticalScroll()
			{
				if (isScrollableV) {

					container.append(
						$('<div class="jspVerticalBar" />').append(
							$('<div class="jspCap jspCapTop" />'),
							$('<div class="jspTrack" />').append(
								$('<div class="jspDrag" />').append(
									$('<div class="jspDragTop" />'),
									$('<div class="jspDragBottom" />')
								)
							),
							$('<div class="jspCap jspCapBottom" />')
						)
					);

					verticalBar = container.find('>.jspVerticalBar');
					verticalTrack = verticalBar.find('>.jspTrack');
					verticalDrag = verticalTrack.find('>.jspDrag');

					if (settings.showArrows) {
						arrowUp = $('<a class="jspArrow jspArrowUp" />').bind(
							'mousedown.jsp', getArrowScroll(0, -1)
						).bind('click.jsp', nil);
						arrowDown = $('<a class="jspArrow jspArrowDown" />').bind(
							'mousedown.jsp', getArrowScroll(0, 1)
						).bind('click.jsp', nil);
						if (settings.arrowScrollOnHover) {
							arrowUp.bind('mouseover.jsp', getArrowScroll(0, -1, arrowUp));
							arrowDown.bind('mouseover.jsp', getArrowScroll(0, 1, arrowDown));
						}

						appendArrows(verticalTrack, settings.verticalArrowPositions, arrowUp, arrowDown);
					}

					verticalTrackHeight = paneHeight;
					container.find('>.jspVerticalBar>.jspCap:visible,>.jspVerticalBar>.jspArrow').each(
						function()
						{
							verticalTrackHeight -= $(this).outerHeight();
						}
					);


					verticalDrag.hover(
						function()
						{
							verticalDrag.addClass('jspHover');
						},
						function()
						{
							verticalDrag.removeClass('jspHover');
						}
					).bind(
						'mousedown.jsp',
						function(e)
						{
							// Stop IE from allowing text selection
							$('html').bind('dragstart.jsp selectstart.jsp', function() { return false; });

							verticalDrag.addClass('jspActive');

							var startY = e.pageY - verticalDrag.position().top;

							$('html').bind(
								'mousemove.jsp',
								function(e)
								{
									positionDragY(e.pageY - startY, false);
								}
							).bind('mouseup.jsp mouseleave.jsp', cancelDrag);
							return false;
						}
					);
					sizeVerticalScrollbar();
				}
			}

			function sizeVerticalScrollbar()
			{
				verticalTrack.height(verticalTrackHeight + 'px');
				verticalDragPosition = 0;
				scrollbarWidth = settings.verticalGutter + verticalTrack.outerWidth();

				// Make the pane thinner to allow for the vertical scrollbar
				pane.width(paneWidth - scrollbarWidth - originalPaddingTotalWidth);

				// Add margin to the left of the pane if scrollbars are on that side (to position
				// the scrollbar on the left or right set it's left or right property in CSS)
				if (verticalBar.position().left == 0) {
					pane.css('margin-left', scrollbarWidth + 'px');
				}
			}

			function initialiseHorizontalScroll()
			{
				if (isScrollableH) {

					container.append(
						$('<div class="jspHorizontalBar" />').append(
							$('<div class="jspCap jspCapLeft" />'),
							$('<div class="jspTrack" />').append(
								$('<div class="jspDrag" />').append(
									$('<div class="jspDragLeft" />'),
									$('<div class="jspDragRight" />')
								)
							),
							$('<div class="jspCap jspCapRight" />')
						)
					);

					horizontalBar = container.find('>.jspHorizontalBar');
					horizontalTrack = horizontalBar.find('>.jspTrack');
					horizontalDrag = horizontalTrack.find('>.jspDrag');

					if (settings.showArrows) {
						arrowLeft = $('<a class="jspArrow jspArrowLeft" />').bind(
							'mousedown.jsp', getArrowScroll(-1, 0)
						).bind('click.jsp', nil);
						arrowRight = $('<a class="jspArrow jspArrowRight" />').bind(
							'mousedown.jsp', getArrowScroll(1, 0)
						).bind('click.jsp', nil);
						if (settings.arrowScrollOnHover) {
							arrowLeft.bind('mouseover.jsp', getArrowScroll(-1, 0, arrowLeft));
							arrowRight.bind('mouseover.jsp', getArrowScroll(1, 0, arrowRight));
						}
						appendArrows(horizontalTrack, settings.horizontalArrowPositions, arrowLeft, arrowRight);
					}

					horizontalDrag.hover(
						function()
						{
							horizontalDrag.addClass('jspHover');
						},
						function()
						{
							horizontalDrag.removeClass('jspHover');
						}
					).bind(
						'mousedown.jsp',
						function(e)
						{
							// Stop IE from allowing text selection
							$('html').bind('dragstart.jsp selectstart.jsp', function() { return false; });

							horizontalDrag.addClass('jspActive');

							var startX = e.pageX - horizontalDrag.position().left;

							$('html').bind(
								'mousemove.jsp',
								function(e)
								{
									positionDragX(e.pageX - startX, false);
								}
							).bind('mouseup.jsp mouseleave.jsp', cancelDrag);
							return false;
						}
					);
					horizontalTrackWidth = container.innerWidth();
					sizeHorizontalScrollbar();
				} else {
					// no horizontal scroll
				}
			}

			function sizeHorizontalScrollbar()
			{

				container.find('>.jspHorizontalBar>.jspCap:visible,>.jspHorizontalBar>.jspArrow').each(
					function()
					{
						horizontalTrackWidth -= $(this).outerWidth();
					}
				);

				horizontalTrack.width(horizontalTrackWidth + 'px');
				horizontalDragPosition = 0;
			}

			function resizeScrollbars()
			{
				if (isScrollableH && isScrollableV) {
					var horizontalTrackHeight = horizontalTrack.outerHeight(),
						verticalTrackWidth = verticalTrack.outerWidth();
					verticalTrackHeight -= horizontalTrackHeight;
					$(horizontalBar).find('>.jspCap:visible,>.jspArrow').each(
						function()
						{
							horizontalTrackWidth += $(this).outerWidth();
						}
					);
					horizontalTrackWidth -= verticalTrackWidth;
					paneHeight -= verticalTrackWidth;
					paneWidth -= horizontalTrackHeight;
					horizontalTrack.parent().append(
						$('<div class="jspCorner" />').css('width', horizontalTrackHeight + 'px')
					);
					sizeVerticalScrollbar();
					sizeHorizontalScrollbar();
				}
				// reflow content
				if (isScrollableH) {
					pane.width((container.outerWidth() - originalPaddingTotalWidth) + 'px');
				}
				contentHeight = pane.outerHeight();
				percentInViewV = contentHeight / paneHeight;

				if (isScrollableH) {
					horizontalDragWidth = 1 / percentInViewH * horizontalTrackWidth;
					if (horizontalDragWidth > settings.horizontalDragMaxWidth) {
						horizontalDragWidth = settings.horizontalDragMaxWidth;
					} else if (horizontalDragWidth < settings.horizontalDragMinWidth) {
						horizontalDragWidth = settings.horizontalDragMinWidth;
					}
					horizontalDrag.width(horizontalDragWidth + 'px');
					dragMaxX = horizontalTrackWidth - horizontalDragWidth;
					_positionDragX(horizontalDragPosition); // To update the state for the arrow buttons
				}
				if (isScrollableV) {
					verticalDragHeight = 1 / percentInViewV * verticalTrackHeight;
					if (verticalDragHeight > settings.verticalDragMaxHeight) {
						verticalDragHeight = settings.verticalDragMaxHeight;
					} else if (verticalDragHeight < settings.verticalDragMinHeight) {
						verticalDragHeight = settings.verticalDragMinHeight;
					}
					verticalDrag.height(verticalDragHeight + 'px');
					dragMaxY = verticalTrackHeight - verticalDragHeight;
					_positionDragY(verticalDragPosition); // To update the state for the arrow buttons
				}
			}

			function appendArrows(ele, p, a1, a2)
			{
				var p1 = "before", p2 = "after", aTemp;
				
				// Sniff for mac... Is there a better way to determine whether the arrows would naturally appear
				// at the top or the bottom of the bar?
				if (p == "os") {
					p = /Mac/.test(navigator.platform) ? "after" : "split";
				}
				if (p == p1) {
					p2 = p;
				} else if (p == p2) {
					p1 = p;
					aTemp = a1;
					a1 = a2;
					a2 = aTemp;
				}

				ele[p1](a1)[p2](a2);
			}

			function getArrowScroll(dirX, dirY, ele) {
				return function()
				{
					arrowScroll(dirX, dirY, this, ele);
					this.blur();
					return false;
				}
			}

			function arrowScroll(dirX, dirY, arrow, ele)
			{
				arrow = $(arrow).addClass('jspActive');

				var eve, doScroll = function()
					{
						if (dirX != 0) {
							positionDragX(horizontalDragPosition + dirX * settings.arrowButtonSpeed, false);
						}
						if (dirY != 0) {
							positionDragY(verticalDragPosition + dirY * settings.arrowButtonSpeed, false);
						}
					},
					scrollInt = setInterval(doScroll, settings.arrowRepeatFreq);

				doScroll();

				eve = ele == undefined ? 'mouseup.jsp' : 'mouseout.jsp';
				ele = ele || $('html');
				ele.bind(
					eve,
					function()
					{
						arrow.removeClass('jspActive');
						clearInterval(scrollInt);
						ele.unbind(eve);
					}
				);
			}

			function initClickOnTrack()
			{
				removeClickOnTrack();
				if (isScrollableV) {
					verticalTrack.bind(
						'mousedown.jsp',
						function(e)
						{
							if (e.originalTarget == undefined || e.originalTarget == e.currentTarget) {
								var clickedTrack = $(this),
									scrollInt = setInterval(
										function()
										{
											var offset = clickedTrack.offset(), pos = e.pageY - offset.top;
											if (verticalDragPosition + verticalDragHeight < pos) {
												positionDragY(verticalDragPosition + settings.trackClickSpeed);
											} else if (pos < verticalDragPosition) {
												positionDragY(verticalDragPosition - settings.trackClickSpeed);
											} else {
												cancelClick();
											}
										},
										settings.trackClickRepeatFreq
									),
									cancelClick = function()
									{
										scrollInt && clearInterval(scrollInt);
										scrollInt = null;
										$(document).unbind('mouseup.jsp', cancelClick);
									};
								$(document).bind('mouseup.jsp', cancelClick);
								return false;
							}
						}
					);
				}
				if (isScrollableH) {
					horizontalTrack.bind(
						'mousedown.jsp',
						function(e)
						{
							if (e.originalTarget == undefined || e.originalTarget == e.currentTarget) {
								var clickedTrack = $(this),
									scrollInt = setInterval(
										function()
										{
											var offset = clickedTrack.offset(), pos = e.pageX - offset.left;
											if (horizontalDragPosition + horizontalDragWidth < pos) {
												positionDragX(horizontalDragPosition + settings.trackClickSpeed);
											} else if (pos < horizontalDragPosition) {
												positionDragX(horizontalDragPosition - settings.trackClickSpeed);
											} else {
												cancelClick();
											}
										},
										settings.trackClickRepeatFreq
									),
									cancelClick = function()
									{
										scrollInt && clearInterval(scrollInt);
										scrollInt = null;
										$(document).unbind('mouseup.jsp', cancelClick);
									};
								$(document).bind('mouseup.jsp', cancelClick);
								return false;
							}
						}
					);
				}
			}

			function removeClickOnTrack()
			{
				horizontalTrack && horizontalTrack.unbind('mousedown.jsp');
				verticalTrack && verticalTrack.unbind('mousedown.jsp');
			}

			function cancelDrag()
			{
				$('html').unbind('dragstart.jsp selectstart.jsp mousemove.jsp mouseup.jsp mouseleave.jsp');

				verticalDrag && verticalDrag.removeClass('jspActive');
				horizontalDrag && horizontalDrag.removeClass('jspActive');
			}

			function positionDragY(destY, animate)
			{
				if (!isScrollableV) {
					return;
				}
				if (destY < 0) {
					destY = 0;
				} else if (destY > dragMaxY) {
					destY = dragMaxY;
				}

				// can't just check if(animate) because false is a valid value that could be passed in...
				if (animate == undefined) {
					animate = settings.animateScroll;
				}
				if (animate) {
					jsp.animate(verticalDrag, 'top', destY,	_positionDragY);
				} else {
					verticalDrag.css('top', destY);
					_positionDragY(destY);
				}

			}

			function _positionDragY(destY)
			{
				if (destY == undefined) {
					destY = verticalDrag.position().top;
				}

				container.scrollTop(0);
				verticalDragPosition = destY;

				var isAtTop = verticalDragPosition == 0,
					isAtBottom = verticalDragPosition == dragMaxY,
					percentScrolled = destY/ dragMaxY,
					destTop = -percentScrolled * (contentHeight - paneHeight);

				if (wasAtTop != isAtTop || wasAtBottom != isAtBottom) {
					wasAtTop = isAtTop;
					wasAtBottom = isAtBottom;
					elem.trigger('jsp-arrow-change', [wasAtTop, wasAtBottom, wasAtLeft, wasAtRight]);
				}
				
				updateVerticalArrows(isAtTop, isAtBottom);
				pane.css('top', destTop);
				elem.trigger('jsp-scroll-y', [-destTop, isAtTop, isAtBottom]);
			}

			function positionDragX(destX, animate)
			{
				if (!isScrollableH) {
					return;
				}
				if (destX < 0) {
					destX = 0;
				} else if (destX > dragMaxX) {
					destX = dragMaxX;
				}

				if (animate == undefined) {
					animate = settings.animateScroll;
				}
				if (animate) {
					jsp.animate(horizontalDrag, 'left', destX,	_positionDragX);
				} else {
					horizontalDrag.css('left', destX);
					_positionDragX(destX);
				}
			}

			function _positionDragX(destX)
			{
				if (destX == undefined) {
					destX = horizontalDrag.position().left;
				}

				container.scrollTop(0);
				horizontalDragPosition = destX;

				var isAtLeft = horizontalDragPosition == 0,
					isAtRight = horizontalDragPosition == dragMaxX,
					percentScrolled = destX / dragMaxX,
					destLeft = -percentScrolled * (contentWidth - paneWidth);

				if (wasAtLeft != isAtLeft || wasAtRight != isAtRight) {
					wasAtLeft = isAtLeft;
					wasAtRight = isAtRight;
					elem.trigger('jsp-arrow-change', [wasAtTop, wasAtBottom, wasAtLeft, wasAtRight]);
				}
				
				updateHorizontalArrows(isAtLeft, isAtRight);
				pane.css('left', destLeft);
				elem.trigger('jsp-scroll-x', [-destLeft, isAtLeft, isAtRight]);
			}

			function updateVerticalArrows(isAtTop, isAtBottom)
			{
				if (settings.showArrows) {
					arrowUp[isAtTop ? 'addClass' : 'removeClass']('jspDisabled');
					arrowDown[isAtBottom ? 'addClass' : 'removeClass']('jspDisabled');
				}
			}

			function updateHorizontalArrows(isAtLeft, isAtRight)
			{
				if (settings.showArrows) {
					arrowLeft[isAtLeft ? 'addClass' : 'removeClass']('jspDisabled');
					arrowRight[isAtRight ? 'addClass' : 'removeClass']('jspDisabled');
				}
			}

			function scrollToY(destY, animate)
			{
				var percentScrolled = destY / (contentHeight - paneHeight);
				positionDragY(percentScrolled * dragMaxY, animate);
			}

			function scrollToX(destX, animate)
			{
				var percentScrolled = destX / (contentWidth - paneWidth);
				positionDragX(percentScrolled * dragMaxX, animate);
			}

			function scrollToElement(ele, stickToTop, animate)
			{
				var e, eleHeight, eleTop = 0, viewportTop, maxVisibleEleTop, destY;

				// Legal hash values aren't necessarily legal jQuery selectors so we need to catch any
				// errors from the lookup...
				try {
					e = $(ele);
				} catch (err) {
					return;
				}
				eleHeight = e.outerHeight();

				container.scrollTop(0);
				
				// loop through parents adding the offset top of any elements that are relatively positioned between
				// the focused element and the jspPane so we can get the true distance from the top
				// of the focused element to the top of the scrollpane...
				while (!e.is('.jspPane')) {
					eleTop += e.position().top;
					e = e.offsetParent();
					if (/^body|html$/i.test(e[0].nodeName)) {
						// we ended up too high in the document structure. Quit!
						return;
					}
				}


				viewportTop = contentPositionY();
				maxVisibleEleTop = viewportTop + paneHeight;
				if (eleTop < viewportTop || stickToTop) { // element is above viewport
					destY = eleTop - settings.verticalGutter;
				} else if (eleTop + eleHeight > maxVisibleEleTop) { // element is below viewport
					destY = eleTop - paneHeight + eleHeight + settings.verticalGutter;
				}
				if (destY) {
					scrollToY(destY, animate);
				}
				// TODO: Implement automatic horizontal scrolling?
			}

			function contentPositionX()
			{
				return -pane.position().left;
			}

			function contentPositionY()
			{
				return -pane.position().top;
			}

			function initMousewheel()
			{
				container.unbind(mwEvent).bind(
					mwEvent,
					function (event, delta, deltaX, deltaY) {
						var dX = horizontalDragPosition, dY = verticalDragPosition;
						positionDragX(horizontalDragPosition + deltaX * settings.mouseWheelSpeed, false)
						positionDragY(verticalDragPosition - deltaY * settings.mouseWheelSpeed, false);
						// return true if there was no movement so rest of screen can scroll
						return dX == horizontalDragPosition && dY == verticalDragPosition;
					}
				);
			}

			function removeMousewheel()
			{
				container.unbind(mwEvent);
			}

			function nil()
			{
				return false;
			}

			function initFocusHandler()
			{
				pane.unbind('focusin.jsp').bind(
					'focusin.jsp',
					function(e)
					{
						if(e.target === pane[0]){return;}
						scrollToElement(e.target, false);
					}
				);
			}

			function removeFocusHandler()
			{

				pane.unbind('focusin.jsp');
			}
			
			function initKeyboardNav()
			{
				var pressed, pressedTimer;
				elem.attr('tabindex', 0)
					.unbind('keydown.jsp')
					.bind(
						'keydown.jsp',
						function(e)
						{
							if(e.target !== elem[0]){
								return;
							}
							var dX = horizontalDragPosition, dY = verticalDragPosition, step = pressed ? 2 : 16;
							switch(e.keyCode) {
								case 40: // down
									positionDragY(verticalDragPosition + step, false);
									break;
								case 38: // up
									positionDragY(verticalDragPosition - step, false);
									break;
								case 34: // page down
								case 32: // space
									scrollToY(contentPositionY() + Math.max(32, paneHeight) - 16);
									break;
								case 33: // page up
									scrollToY(contentPositionY() - paneHeight + 16);
									break;
								case 35: // end
									scrollToY(contentHeight - paneHeight);
									break;
								case 36: // home
									scrollToY(0);
									break;
								case 39: // right
									positionDragX(horizontalDragPosition + step, false);
									break;
								case 37: // left
									positionDragX(horizontalDragPosition - step, false);
									break;
							}

							if( !(dX == horizontalDragPosition && dY == verticalDragPosition) ){
								pressed = true;
								clearTimeout(pressedTimer);
								pressedTimer = setTimeout(function(){
									pressed = false;
								}, 260);
								return false;
							}
						}
					);
				if(settings.hideFocus) {
					elem.css('outline', 'none');
					if('hideFocus' in container[0]){
						elem.attr('hideFocus', true);
					}
				} else {
					elem.css('outline', '');
					if('hideFocus' in container[0]){
						elem.attr('hideFocus', false);
					}
				}
			}
			
			function removeKeyboardNav()
			{
				elem.attr('tabindex', '-1')
					.removeAttr('tabindex')
					.unbind('keydown.jsp');
			}

			function observeHash()
			{
				if (location.hash && location.hash.length > 1) {
					var e, retryInt;
					try {
						e = $(location.hash);
					} catch (err) {
						return;
					}

					if (e.length && pane.find(e)) {
						// nasty workaround but it appears to take a little while before the hash has done its thing
						// to the rendered page so we just wait until the container's scrollTop has been messed up.
						if (container.scrollTop() == 0) {
							retryInt = setInterval(
								function()
								{
									if (container.scrollTop() > 0) {
										scrollToElement(location.hash, true);
										$(document).scrollTop(container.position().top);
										clearInterval(retryInt);
									}
								},
								50
							)
						} else {
							scrollToElement(location.hash, true);
							$(document).scrollTop(container.position().top);
						}
					}
				}
			}

			function unhijackInternalLinks()
			{
				$('a.jspHijack').unbind('click.jsp-hijack').removeClass('jspHijack');
			}

			function hijackInternalLinks()
			{
				unhijackInternalLinks();
				$('a[href^=#]').addClass('jspHijack').bind(
					'click.jsp-hijack',
					function()
					{
						var uriParts = this.href.split('#'), hash;
						if (uriParts.length > 1) {
							hash = uriParts[1];
							if (hash.length > 0 && pane.find('#' + hash).length > 0) {
								scrollToElement('#' + hash, true);
								// Need to return false otherwise things mess up... Would be nice to maybe also scroll
								// the window to the top of the scrollpane?
								return false;
							}
						}
					}
				)
			}

			// Public API
			$.extend(
				jsp,
				{
					// Reinitialises the scroll pane (if it's internal dimensions have changed since the last time it
					// was initialised). The settings object which is passed in will override any settings from the
					// previous time it was initialised - if you don't pass any settings then the ones from the previous
					// initialisation will be used.
					reinitialise: function(s)
					{
						s = $.extend({}, s, settings);
						initialise(s);
					},
					// Scrolls the specified element (a jQuery object, DOM node or jQuery selector string) into view so
					// that it can be seen within the viewport. If stickToTop is true then the element will appear at
					// the top of the viewport, if it is false then the viewport will scroll as little as possible to
					// show the element. You can also specify if you want animation to occur. If you don't provide this
					// argument then the animateScroll value from the settings object is used instead.
					scrollToElement: function(ele, stickToTop, animate)
					{
						scrollToElement(ele, stickToTop, animate);
					},
					// Scrolls the pane so that the specified co-ordinates within the content are at the top left
					// of the viewport. animate is optional and if not passed then the value of animateScroll from
					// the settings object this jScrollPane was initialised with is used.
					scrollTo: function(destX, destY, animate)
					{
						scrollToX(destX, animate);
						scrollToY(destY, animate);
					},
					// Scrolls the pane so that the specified co-ordinate within the content is at the left of the
					// viewport. animate is optional and if not passed then the value of animateScroll from the settings
					// object this jScrollPane was initialised with is used.
					scrollToX: function(destX, animate)
					{
						scrollToX(destX, animate);
					},
					// Scrolls the pane so that the specified co-ordinate within the content is at the top of the
					// viewport. animate is optional and if not passed then the value of animateScroll from the settings
					// object this jScrollPane was initialised with is used.
					scrollToY: function(destY, animate)
					{
						scrollToY(destY, animate);
					},
					// Scrolls the pane by the specified amount of pixels. animate is optional and if not passed then
					// the value of animateScroll from the settings object this jScrollPane was initialised with is used.
					scrollBy: function(deltaX, deltaY, animate)
					{
						jsp.scrollByX(deltaX, animate);
						jsp.scrollByY(deltaY, animate);
					},
					// Scrolls the pane by the specified amount of pixels. animate is optional and if not passed then
					// the value of animateScroll from the settings object this jScrollPane was initialised with is used.
					scrollByX: function(deltaX, animate)
					{
						var destX = contentPositionX() + deltaX,
							percentScrolled = destX / (contentWidth - paneWidth);
						positionDragX(percentScrolled * dragMaxX, animate);
					},
					// Scrolls the pane by the specified amount of pixels. animate is optional and if not passed then
					// the value of animateScroll from the settings object this jScrollPane was initialised with is used.
					scrollByY: function(deltaY, animate)
					{
						var destY = contentPositionY() + deltaY,
							percentScrolled = destY / (contentHeight - paneHeight);
						positionDragY(percentScrolled * dragMaxY, animate);
					},
					// This method is called when jScrollPane is trying to animate to a new position. You can override
					// it if you want to provide advanced animation functionality. It is passed the following arguments:
					//  * ele          - the element whose position is being animated
					//  * prop         - the property that is being animated
					//  * value        - the value it's being animated to
					//  * stepCallback - a function that you must execute each time you update the value of the property
					// You can use the default implementation (below) as a starting point for your own implementation.
					animate: function(ele, prop, value, stepCallback)
					{
						var params = {};
						params[prop] = value;
						ele.animate(
							params,
							{
								'duration'	: settings.animateDuration,
								'ease'		: settings.animateEase,
								'queue'		: false,
								'step'		: stepCallback
							}
						);
					},
					// Returns the current x position of the viewport with regards to the content pane.
					getContentPositionX: function()
					{
						return contentPositionX();
					},
					// Returns the current y position of the viewport with regards to the content pane.
					getContentPositionY: function()
					{
						return contentPositionY();
					},
					// Returns whether or not this scrollpane has a horizontal scrollbar.
					getIsScrollableH: function()
					{
						return isScrollableH;
					},
					// Returns whether or not this scrollpane has a vertical scrollbar.
					getIsScrollableV: function()
					{
						return isScrollableV;
					},
					// Gets a reference to the content pane. It is important that you use this method if you want to
					// edit the content of your jScrollPane as if you access the element directly then you may have some
					// problems (as your original element has had additional elements for the scrollbars etc added into
					// it).
					getContentPane: function()
					{
						return pane;
					},
					// Scrolls this jScrollPane down as far as it can currently scroll. If animate isn't passed then the
					// animateScroll value from settings is used instead.
					scrollToBottom: function(animate)
					{
						positionDragY(dragMaxY, animate);
					},
					// Hijacks the links on the page which link to content inside the scrollpane. If you have changed
					// the content of your page (e.g. via AJAX) and want to make sure any new anchor links to the
					// contents of your scroll pane will work then call this function.
					hijackInternalLinks: function()
					{
						hijackInternalLinks();
					}
				}
			);
		}

		// Pluginifying code...

		settings = $.extend({}, $.fn.jScrollPane.defaults, settings);

		var ret;
		this.each(
			function()
			{
				var elem = $(this), jspApi = elem.data('jsp');
				if (jspApi) {
					jspApi.reinitialise(settings);
				} else {
					jspApi = new JScrollPane(elem, settings);
					elem.data('jsp', jspApi);
				}
				ret = ret ? ret.add(elem) : elem;
			}
		)
		return ret;
	};

	$.fn.jScrollPane.defaults = {
		'showArrows'				: false,
		'maintainPosition'			: true,
		'clickOnTrack'				: true,
		'autoReinitialise'			: false,
		'autoReinitialiseDelay'		: 500,
		'verticalDragMinHeight'		: 0,
		'verticalDragMaxHeight'		: 99999,
		'horizontalDragMinWidth'	: 0,
		'horizontalDragMaxWidth'	: 99999,
		'animateScroll'				: false,
		'animateDuration'			: 300,
		'animateEase'				: 'linear',
		'hijackInternalLinks'		: false,
		'verticalGutter'			: 4,
		'horizontalGutter'			: 4,
		'mouseWheelSpeed'			: 10,
		'arrowButtonSpeed'			: 10,
		'arrowRepeatFreq'			: 100,
		'arrowScrollOnHover'		: false,
		'trackClickSpeed'			: 30,
		'trackClickRepeatFreq'		: 100,
		'verticalArrowPositions'	: 'split',
		'horizontalArrowPositions'	: 'split',
		'enableKeyboardNavigation'	: true,
		'hideFocus'					: false
	};

})(jQuery,this);


/* Copyright (c) 2006 Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
 * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
 *
 * $LastChangedDate: 2007-06-20 16:25:35 -0500 (Wed, 20 Jun 2007) $
 * $Rev: 2125 $
 *
 * Version: 2.2
 */
(function($){$.fn.extend({mousewheel:function(f){if(!f.guid)f.guid=$.event.guid++;if(!$.event._mwCache)$.event._mwCache=[];return this.each(function(){if(this._mwHandlers)return this._mwHandlers.push(f);else this._mwHandlers=[];this._mwHandlers.push(f);var s=this;this._mwHandler=function(e){e=$.event.fix(e||window.event);$.extend(e,this._mwCursorPos||{});var delta=0,returnValue=true;if(e.wheelDelta)delta=e.wheelDelta/120;if(e.detail)delta=-e.detail/3;if(window.opera)delta=-e.wheelDelta;for(var i=0;i<s._mwHandlers.length;i++)if(s._mwHandlers[i])if(s._mwHandlers[i].call(s,e,delta)===false){returnValue=false;e.preventDefault();e.stopPropagation();}return returnValue;};if($.browser.mozilla&&!this._mwFixCursorPos){this._mwFixCursorPos=function(e){this._mwCursorPos={pageX:e.pageX,pageY:e.pageY,clientX:e.clientX,clientY:e.clientY};};$(this).bind('mousemove',this._mwFixCursorPos);}if(this.addEventListener)if($.browser.mozilla)this.addEventListener('DOMMouseScroll',this._mwHandler,false);else this.addEventListener('mousewheel',this._mwHandler,false);else
this.onmousewheel=this._mwHandler;$.event._mwCache.push($(this));});},unmousewheel:function(f){return this.each(function(){if(f&&this._mwHandlers){for(var i=0;i<this._mwHandlers.length;i++)if(this._mwHandlers[i]&&this._mwHandlers[i].guid==f.guid)delete this._mwHandlers[i];}else{if($.browser.mozilla&&!this._mwFixCursorPos)$(this).unbind('mousemove',this._mwFixCursorPos);if(this.addEventListener)if($.browser.mozilla)this.removeEventListener('DOMMouseScroll',this._mwHandler,false);else this.removeEventListener('mousewheel',this._mwHandler,false);else
this.onmousewheel=null;this._mwHandlers=this._mwHandler=this._mwFixCursorPos=this._mwCursorPos=null;}});}});$(window).one('unload',function(){var els=$.event._mwCache||[];for(var i=0;i<els.length;i++)els[i].unmousewheel();});})(jQuery);

// ==ClosureCompiler==
// @compilation_level ADVANCED_OPTIMIZATIONS
// @externs_url http://closure-compiler.googlecode.com/svn/trunk/contrib/externs/maps/google_maps_api_v3.js
// ==/ClosureCompiler==

/**
 * @name CSS3 InfoBubble with tabs for Google Maps API V3
 * @version 0.8
 * @author Luke Mahe
 * @fileoverview
 * This library is a CSS Infobubble with tabs. It uses css3 rounded corners and
 * drop shadows and animations. It also allows tabs
 */

/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


/**
 * A CSS3 InfoBubble v0.8
 * @param {Object.<string, *>=} opt_options Optional properties to set.
 * @extends {google.maps.OverlayView}
 * @constructor
 */
function InfoBubble(opt_options) {
  this.extend(InfoBubble, google.maps.OverlayView);
  this.tabs_ = [];
  this.activeTab_ = null;
  this.baseZIndex_ = 100;
  this.isOpen_ = false;

  var options = opt_options || {};

  if (options['backgroundColor'] == undefined) {
    options['backgroundColor'] = this.BACKGROUND_COLOR_;
  }

  if (options['borderColor'] == undefined) {
    options['borderColor'] = this.BORDER_COLOR_;
  }

  if (options['borderRadius'] == undefined) {
    options['borderRadius'] = this.BORDER_RADIUS_;
  }

  if (options['borderWidth'] == undefined) {
    options['borderWidth'] = this.BORDER_WIDTH_;
  }

  if (options['padding'] == undefined) {
    options['padding'] = this.PADDING_;
  }

  if (options['arrowPosition'] == undefined) {
    options['arrowPosition'] = this.ARROW_POSITION_;
  }

  if (options['disableAutoPan'] == undefined) {
    options['disableAutoPan'] = false;
  }

  if (options['disableAnimation'] == undefined) {
    options['disableAnimation'] = false;
  }

  if (options['minWidth'] == undefined) {
    options['minWidth'] = this.MIN_WIDTH_;
  }

  if (options['shadowStyle'] == undefined) {
    options['shadowStyle'] = this.SHADOW_STYLE_;
  }

  if (options['arrowSize'] == undefined) {
    options['arrowSize'] = this.ARROW_SIZE_;
  }

  if (options['arrowStyle'] == undefined) {
    options['arrowStyle'] = this.ARROW_STYLE_;
  }

  if (options['closeWidth'] == undefined) {
    options['closeWidth'] = this.CLOSE_WIDTH_;
  }

  if (options['closeHeight'] == undefined) {
    options['closeHeight'] = this.CLOSE_HEIGHT_;
  }

  if (options['closeImage'] == undefined) {
    options['closeImage'] = this.CLOSE_IMAGE_;
  }


  this.buildDom_();

  this.setValues(options);
}
window['InfoBubble'] = InfoBubble;


/**
 * Default arrow size
 * @const
 * @private
 */
InfoBubble.prototype.ARROW_SIZE_ = 15;


/**
 * Default arrow style
 * @const
 * @private
 */
InfoBubble.prototype.ARROW_STYLE_ = 0;


/**
 * Default shadow style
 * @const
 * @private
 */
InfoBubble.prototype.SHADOW_STYLE_ = 1;


/**
 * Default min width
 * @const
 * @private
 */
InfoBubble.prototype.MIN_WIDTH_ = 50;


/**
 * Default arrow position
 * @const
 * @private
 */
InfoBubble.prototype.ARROW_POSITION_ = 50;


/**
 * Default padding
 * @const
 * @private
 */
InfoBubble.prototype.PADDING_ = 10;


/**
 * Default border width
 * @const
 * @private
 */
InfoBubble.prototype.BORDER_WIDTH_ = 1;


/**
 * Default border color
 * @const
 * @private
 */
InfoBubble.prototype.BORDER_COLOR_ = '#ccc';


/**
 * Default border radius
 * @const
 * @private
 */
InfoBubble.prototype.BORDER_RADIUS_ = 10;


/**
 * Default background color
 * @const
 * @private
 */
InfoBubble.prototype.BACKGROUND_COLOR_ = '#fff';

InfoBubble.prototype.CLOSE_WIDTH_ = 12;
InfoBubble.prototype.CLOSE_HEIGHT_ = 12;
InfoBubble.prototype.CLOSE_IMAGE_ = '/img/front/soundplace/infowindow-close.png';


/**
 * Extends a objects prototype by anothers.
 *
 * @param {Object} obj1 The object to be extended.
 * @param {Object} obj2 The object to extend with.
 * @return {Object} The new extended object.
 * @ignore
 */
InfoBubble.prototype.extend = function(obj1, obj2) {
  return (function(object) {
    for (var property in object.prototype) {
      this.prototype[property] = object.prototype[property];
    }
    return this;
  }).apply(obj1, [obj2]);
};


/**
 * Builds the InfoBubble dom
 * @private
 */
InfoBubble.prototype.buildDom_ = function() {
  var bubble = this.bubble_ = document.createElement('DIV');
  bubble.style['position'] = 'absolute';
  bubble.style['zIndex'] = this.baseZIndex_;

  var tabsContainer = this.tabsContainer_ = document.createElement('DIV');
  tabsContainer.style['position'] = 'relative';

  // Close button
  var close = this.close_ = document.createElement('IMG');
  close.style['position'] = 'absolute';
  close.style['width'] = this.px(16);
  close.style['height'] = this.px(16);
  close.style['border'] = 0;
  close.style['zIndex'] = this.baseZIndex_ + 1;
  close.style['cursor'] = 'pointer';
  close.src = '/img/front/soundplace/infowindow-close.png';

  var that = this;
  google.maps.event.addDomListener(close, 'click', function() {
    that.close();
    google.maps.event.trigger(that, 'closeclick');
  });

  // Content area
  var contentContainer = this.contentContainer_ = document.createElement('DIV');
  contentContainer.style['overflowX'] = 'auto';
  contentContainer.style['overflowY'] = 'auto';
  contentContainer.style['cursor'] = 'default';
  contentContainer.style['clear'] = 'both';
  contentContainer.style['position'] = 'relative';

  var content = this.content_ = document.createElement('DIV');
  contentContainer.appendChild(content);

  // Arrow
  var arrow = this.arrow_ = document.createElement('DIV');
  arrow.style['position'] = 'relative';

  var arrowOuter = this.arrowOuter_ = document.createElement('DIV');
  var arrowInner = this.arrowInner_ = document.createElement('DIV');

  var arrowSize = this.getArrowSize_();

  arrowOuter.style['position'] = arrowInner.style['position'] = 'absolute';
  arrowOuter.style['left'] = arrowInner.style['left'] = '50%';
  arrowOuter.style['height'] = arrowInner.style['height'] = '0';
  arrowOuter.style['width'] = arrowInner.style['width'] = '0';
  arrowOuter.style['marginLeft'] = this.px(-arrowSize);
  arrowOuter.style['borderWidth'] = this.px(arrowSize);
  arrowOuter.style['borderBottomWidth'] = 0;

  // Shadow
  var bubbleShadow = this.bubbleShadow_ = document.createElement('DIV');
  bubbleShadow.style['position'] = 'absolute';

  // Hide the InfoBubble by default
  bubble.style['display'] = bubbleShadow.style['display'] = 'none';

  bubble.appendChild(this.tabsContainer_);
  bubble.appendChild(close);
  bubble.appendChild(contentContainer);
  arrow.appendChild(arrowOuter);
  arrow.appendChild(arrowInner);
  bubble.appendChild(arrow);

  var stylesheet = document.createElement('style');
  stylesheet.setAttribute('type', 'text/css');

  /**
   * The animation for the infobubble
   * @type {string}
   */
  this.animationName_ = '_ibani_' + Math.round(Math.random() * 10000);

  var css = '.' + this.animationName_ + '{-webkit-animation-name:' +
      this.animationName_ + ';-webkit-animation-duration:0.5s;' +
      '-webkit-animation-iteration-count:1;}' +
      '@-webkit-keyframes ' + this.animationName_ + ' {from {' +
      '-webkit-transform: scale(0)}50% {-webkit-transform: scale(1.2)}90% ' +
      '{-webkit-transform: scale(0.95)}to {-webkit-transform: scale(1)}}';

  stylesheet.textContent = css;
  document.getElementsByTagName('head')[0].appendChild(stylesheet);
};


/**
 * Sets the background class name
 *
 * @param {string} className The class name to set.
 */
InfoBubble.prototype.setBackgroundClassName = function(className) {
  this.set('backgroundClassName', className);
};
InfoBubble.prototype['setBackgroundClassName'] =
    InfoBubble.prototype.setBackgroundClassName;


/**
 * changed MVC callback
 */
InfoBubble.prototype.backgroundClassName_changed = function() {
  this.content_.className = this.get('backgroundClassName');
};
InfoBubble.prototype['backgroundClassName_changed'] =
    InfoBubble.prototype.backgroundClassName_changed;


/**
 * Sets the class of the tab
 *
 * @param {string} className the class name to set.
 */
InfoBubble.prototype.setTabClassName = function(className) {
  this.set('tabClassName', className);
};
InfoBubble.prototype['setTabClassName'] =
    InfoBubble.prototype.setTabClassName;


/**
 * tabClassName changed MVC callback
 */
InfoBubble.prototype.tabClassName_changed = function() {
  this.updateTabStyles_();
};
InfoBubble.prototype['tabClassName_changed'] =
    InfoBubble.prototype.tabClassName_changed;


/**
 * Gets the style of the arrow
 *
 * @private
 * @return {number} The style of the arrow.
 */
InfoBubble.prototype.getArrowStyle_ = function() {
  return parseInt(this.get('arrowStyle'), 10) || 0;
};


/**
 * Sets the style of the arrow
 *
 * @param {number} style The style of the arrow.
 */
InfoBubble.prototype.setArrowStyle = function(style) {
  this.set('arrowStyle', style);
};
InfoBubble.prototype['setArrowStyle'] =
    InfoBubble.prototype.setArrowStyle;


/**
 * Arrow style changed MVC callback
 */
InfoBubble.prototype.arrowStyle_changed = function() {
  this.arrowSize_changed();
};
InfoBubble.prototype['arrowStyle_changed'] =
    InfoBubble.prototype.arrowStyle_changed;


/**
 * Gets the size of the arrow
 *
 * @private
 * @return {number} The size of the arrow.
 */
InfoBubble.prototype.getArrowSize_ = function() {
  return parseInt(this.get('arrowSize'), 10) || 0;
};


/**
 * Sets the size of the arrow
 *
 * @param {number} size The size of the arrow.
 */
InfoBubble.prototype.setArrowSize = function(size) {
  this.set('arrowSize', size);
};
InfoBubble.prototype['setArrowSize'] =
    InfoBubble.prototype.setArrowSize;


/**
 * Arrow size changed MVC callback
 */
InfoBubble.prototype.arrowSize_changed = function() {
  this.borderWidth_changed();
};
InfoBubble.prototype['arrowSize_changed'] =
    InfoBubble.prototype.arrowSize_changed;


/**
 * Set the position of the InfoBubble arrow
 *
 * @param {number} pos The position to set.
 */
InfoBubble.prototype.setArrowPosition = function(pos) {
  this.set('arrowPosition', pos);
};
InfoBubble.prototype['setArrowPosition'] =
    InfoBubble.prototype.setArrowPosition;


/**
 * Get the position of the InfoBubble arrow
 *
 * @private
 * @return {number} The position..
 */
InfoBubble.prototype.getArrowPosition_ = function() {
  return parseInt(this.get('arrowPosition'), 10) || 0;
};


/**
 * arrowPosition changed MVC callback
 */
InfoBubble.prototype.arrowPosition_changed = function() {
  var pos = this.getArrowPosition_();
  this.arrowOuter_.style['left'] = this.arrowInner_.style['left'] = pos + '%';

  this.redraw_();
};
InfoBubble.prototype['arrowPosition_changed'] =
    InfoBubble.prototype.arrowPosition_changed;


/**
 * Set the zIndex of the InfoBubble
 *
 * @param {number} zIndex The zIndex to set.
 */
InfoBubble.prototype.setZIndex = function(zIndex) {
  this.set('zIndex', zIndex);
};
InfoBubble.prototype['setZIndex'] = InfoBubble.prototype.setZIndex;


/**
 * Get the zIndex of the InfoBubble
 *
 * @return {number} The zIndex to set.
 */
InfoBubble.prototype.getZIndex = function() {
  return parseInt(this.get('zIndex'), 10) || this.baseZIndex_;
};


/**
 * zIndex changed MVC callback
 */
InfoBubble.prototype.zIndex_changed = function() {
  var zIndex = this.getZIndex_();

  this.bubble_.style['zIndex'] = this.baseZIndex_ = zIndex;
  this.close_.style['zIndex'] = zIndex_ + 1;
};
InfoBubble.prototype['zIndex_changed'] = InfoBubble.prototype.zIndex_changed;


/**
 * Set the style of the shadow
 *
 * @param {number} shadowStyle The style of the shadow.
 */
InfoBubble.prototype.setShadowStyle = function(shadowStyle) {
  this.set('shadowStyle', shadowStyle);
};
InfoBubble.prototype['setShadowStyle'] = InfoBubble.prototype.setShadowStyle;


/**
 * Get the style of the shadow
 *
 * @private
 * @return {number} The style of the shadow.
 */
InfoBubble.prototype.getShadowStyle_ = function() {
  return parseInt(this.get('shadowStyle'), 10) || 0;
};


/**
 * shadowStyle changed MVC callback
 */
InfoBubble.prototype.shadowStyle_changed = function() {
  var shadowStyle = this.getShadowStyle_();

  var display = '';
  var shadow = '';
  var backgroundColor = '';
  switch (shadowStyle) {
    case 0:
      display = 'none';
      break;
    case 1:
      shadow = '40px 15px 10px rgba(33,33,33,0.3)';
      backgroundColor = 'transparent';
      break;
    case 2:
      shadow = '0 0 2px rgba(33,33,33,0.3)';
      backgroundColor = 'rgba(33,33,33,0.35)';
      break;
  }
  this.bubbleShadow_.style['boxShadow'] =
      this.bubbleShadow_.style['webkitBoxShadow'] =
      this.bubbleShadow_.style['MozBoxShadow'] = shadow;
  this.bubbleShadow_.style['backgroundColor'] = backgroundColor;
  if (this.isOpen_) {
    this.bubbleShadow_.style['display'] = display;
    this.draw();
  }
};
InfoBubble.prototype['shadowStyle_changed'] =
    InfoBubble.prototype.shadowStyle_changed;


/**
 * Show the close button
 */
InfoBubble.prototype.showCloseButton = function() {
  this.set('hideCloseButton', false);
};
InfoBubble.prototype['showCloseButton'] = InfoBubble.prototype.showCloseButton;


/**
 * Hide the close button
 */
InfoBubble.prototype.hideCloseButton = function() {
  this.set('hideCloseButton', true);
};
InfoBubble.prototype['hideCloseButton'] = InfoBubble.prototype.hideCloseButton;


/**
 * hideCloseButton changed MVC callback
 */
InfoBubble.prototype.hideCloseButton_changed = function() {
  this.close_.style['display'] = this.get('hideCloseButton') ? 'none' : '';
};
InfoBubble.prototype['hideCloseButton_changed'] =
    InfoBubble.prototype.hideCloseButton_changed;


/**
 * Set the background color
 *
 * @param {string} color The color to set.
 */
InfoBubble.prototype.setBackgroundColor = function(color) {
  if (color) {
    this.set('backgroundColor', color);
  }
};
InfoBubble.prototype['setBackgroundColor'] =
    InfoBubble.prototype.setBackgroundColor;


/**
 * backgroundColor changed MVC callback
 */
InfoBubble.prototype.backgroundColor_changed = function() {
  var backgroundColor = this.get('backgroundColor');
  this.contentContainer_.style['backgroundColor'] = backgroundColor;

  this.arrowInner_.style['borderColor'] = backgroundColor +
      ' transparent transparent';
  this.updateTabStyles_();
};
InfoBubble.prototype['backgroundColor_changed'] =
    InfoBubble.prototype.backgroundColor_changed;


/**
 * Set the border color
 *
 * @param {string} color The border color.
 */
InfoBubble.prototype.setBorderColor = function(color) {
  if (color) {
    this.set('borderColor', color);
  }
};
InfoBubble.prototype['setBorderColor'] = InfoBubble.prototype.setBorderColor;


/**
 * borderColor changed MVC callback
 */
InfoBubble.prototype.borderColor_changed = function() {
  var borderColor = this.get('borderColor');

  var contentContainer = this.contentContainer_;
  var arrowOuter = this.arrowOuter_;
  contentContainer.style['borderColor'] = borderColor;

  arrowOuter.style['borderColor'] = borderColor +
      ' transparent transparent';

  contentContainer.style['borderStyle'] =
      arrowOuter.style['borderStyle'] =
      this.arrowInner_.style['borderStyle'] = 'solid';

  this.updateTabStyles_();
};
InfoBubble.prototype['borderColor_changed'] =
    InfoBubble.prototype.borderColor_changed;


/**
 * Set the radius of the border
 *
 * @param {number} radius The radius of the border.
 */
InfoBubble.prototype.setBorderRadius = function(radius) {
  this.set('borderRadius', radius);
};
InfoBubble.prototype['setBorderRadius'] = InfoBubble.prototype.setBorderRadius;


/**
 * Get the radius of the border
 *
 * @private
 * @return {number} The radius of the border.
 */
InfoBubble.prototype.getBorderRadius_ = function() {
  return parseInt(this.get('borderRadius'), 10) || 0;
};


/**
 * borderRadius changed MVC callback
 */
InfoBubble.prototype.borderRadius_changed = function() {
  var borderRadius = this.getBorderRadius_();
  var borderWidth = this.getBorderWidth_();

  this.contentContainer_.style['borderRadius'] =
      this.contentContainer_.style['MozBorderRadius'] =
      this.contentContainer_.style['webkitBorderRadius'] =
      this.bubbleShadow_.style['borderRadius'] =
      this.bubbleShadow_.style['MozBorderRadius'] =
      this.bubbleShadow_.style['webkitBorderRadius'] = this.px(borderRadius);

  this.tabsContainer_.style['paddingLeft'] =
      this.tabsContainer_.style['paddingRight'] =
      this.px(borderRadius + borderWidth);

  this.redraw_();
};
InfoBubble.prototype['borderRadius_changed'] =
    InfoBubble.prototype.borderRadius_changed;


/**
 * Get the width of the border
 *
 * @private
 * @return {number} width The width of the border.
 */
InfoBubble.prototype.getBorderWidth_ = function() {
  return parseInt(this.get('borderWidth'), 10) || 0;
};


/**
 * Set the width of the border
 *
 * @param {number} width The width of the border.
 */
InfoBubble.prototype.setBorderWidth = function(width) {
  this.set('borderWidth', width);
};
InfoBubble.prototype['setBorderWidth'] = InfoBubble.prototype.setBorderWidth;


/**
 * borderWidth change MVC callback
 */
InfoBubble.prototype.borderWidth_changed = function() {
  var borderWidth = this.getBorderWidth_();

  this.contentContainer_.style['borderWidth'] = this.px(borderWidth);
  this.tabsContainer_.style['top'] = this.px(borderWidth);

  this.updateArrowStyle_();
  this.updateTabStyles_();
  this.borderRadius_changed();
  this.redraw_();
};
InfoBubble.prototype['borderWidth_changed'] =
    InfoBubble.prototype.borderWidth_changed;


/**
 * Update the arrow style
 * @private
 */
InfoBubble.prototype.updateArrowStyle_ = function() {
  var borderWidth = this.getBorderWidth_();
  var arrowSize = this.getArrowSize_();
  var arrowStyle = this.getArrowStyle_();
  var arrowOuterSizePx = this.px(arrowSize);
  var arrowInnerSizePx = this.px(Math.max(0, arrowSize - borderWidth));

  var outer = this.arrowOuter_;
  var inner = this.arrowInner_;

  this.arrow_.style['marginTop'] = this.px(-borderWidth);
  outer.style['borderTopWidth'] = arrowOuterSizePx;
  inner.style['borderTopWidth'] = arrowInnerSizePx;

  // Full arrow or arrow pointing to the left
  if (arrowStyle == 0 || arrowStyle == 1) {
    outer.style['borderLeftWidth'] = arrowOuterSizePx;
    inner.style['borderLeftWidth'] = arrowInnerSizePx;
  } else {
    outer.style['borderLeftWidth'] = inner.style['borderLeftWidth'] = 0;
  }

  // Full arrow or arrow pointing to the right
  if (arrowStyle == 0 || arrowStyle == 2) {
    outer.style['borderRightWidth'] = arrowOuterSizePx;
    inner.style['borderRightWidth'] = arrowInnerSizePx;
  } else {
    outer.style['borderRightWidth'] = inner.style['borderRightWidth'] = 0;
  }

  if (arrowStyle < 2) {
    outer.style['marginLeft'] = this.px(-(arrowSize));
    inner.style['marginLeft'] = this.px(-(arrowSize - borderWidth));
  } else {
    outer.style['marginLeft'] = inner.style['marginLeft'] = 0;
  }

  // If there is no border then don't show thw outer arrow
  if (borderWidth == 0) {
    outer.style['display'] = 'none';
  } else {
    outer.style['display'] = '';
  }
};


/**
 * Set the padding of the InfoBubble
 *
 * @param {number} padding The padding to apply.
 */
InfoBubble.prototype.setPadding = function(padding) {
  this.set('padding', padding);
};
InfoBubble.prototype['setPadding'] = InfoBubble.prototype.setPadding;


/**
 * Set the padding of the InfoBubble
 *
 * @private
 * @return {number} padding The padding to apply.
 */
InfoBubble.prototype.getPadding_ = function() {
  return parseInt(this.get('padding'), 10) || 0;
};


/**
 * padding changed MVC callback
 */
InfoBubble.prototype.padding_changed = function() {
  var padding = this.getPadding_();
  this.contentContainer_.style['padding'] = this.px(padding);
  this.updateTabStyles_();

  this.redraw_();
};
InfoBubble.prototype['padding_changed'] = InfoBubble.prototype.padding_changed;


/**
 * Add px extention to the number
 *
 * @param {number} num The number to wrap.
 * @return {string|number} A wrapped number.
 */
InfoBubble.prototype.px = function(num) {
  if (num) {
    // 0 doesn't need to be wrapped
    return num + 'px';
  }
  return num;
};


/**
 * Add events to stop propagation
 * @private
 */
InfoBubble.prototype.addEvents_ = function() {
  // We want to cancel all the events so they do not go to the map
  var events = ['mousedown', 'mousemove', 'mouseover', 'mouseout', 'mouseup',
      'mousewheel', 'DOMMouseScroll', 'touchstart', 'touchend', 'touchmove',
      'dblclick', 'contextmenu', 'click'];

  var bubble = this.bubble_;
  this.listeners_ = [];
  for (var i = 0, event; event = events[i]; i++) {
    this.listeners_.push(
      google.maps.event.addDomListener(bubble, event, function(e) {
        e.cancelBubble = true;
        if (e.stopPropagation) {
          e.stopPropagation();
        }
      })
    );
  }
};


/**
 * On Adding the InfoBubble to a map
 * Implementing the OverlayView interface
 */
InfoBubble.prototype.onAdd = function() {
  if (!this.bubble_) {
    this.buildDom_();
  }

  this.addEvents_();

  var panes = this.getPanes();
  if (panes) {
    panes.floatPane.appendChild(this.bubble_);
    panes.floatShadow.appendChild(this.bubbleShadow_);
  }
};
InfoBubble.prototype['onAdd'] = InfoBubble.prototype.onAdd;


/**
 * Draw the InfoBubble
 * Implementing the OverlayView interface
 */
InfoBubble.prototype.draw = function() {
  var projection = this.getProjection();

  if (!projection) {
    // The map projection is not ready yet so do nothing
    return;
  }

  var latLng = /** @type {google.maps.LatLng} */ (this.get('position'));

  if (!latLng) {
    this.close();
    return;
  }

  var tabHeight = 0;

  if (this.activeTab_) {
    tabHeight = this.activeTab_.offsetHeight;
  }

  var anchorHeight = this.getAnchorHeight_();
  var arrowSize = this.getArrowSize_();
  var arrowPosition = this.getArrowPosition_();

  arrowPosition = arrowPosition / 100;

  var pos = projection.fromLatLngToDivPixel(latLng);
  var width = this.contentContainer_.offsetWidth;
  var height = this.bubble_.offsetHeight;

  if (!width) {
    return;
  }

  // Adjust for the height of the info bubble
  var top = pos.y - (height + arrowSize);

  if (anchorHeight) {
    // If there is an anchor then include the height
    top -= anchorHeight;
  }

  var left = pos.x - (width * arrowPosition);

  this.bubble_.style['top'] = this.px(top);
  this.bubble_.style['left'] = this.px(left);

  var shadowStyle = parseInt(this.get('shadowStyle'), 10);

  switch (shadowStyle) {
    case 1:
      // Shadow is behind
      this.bubbleShadow_.style['top'] = this.px(top + tabHeight - 1);
      this.bubbleShadow_.style['left'] = this.px(left);
      this.bubbleShadow_.style['width'] = this.px(width);
      this.bubbleShadow_.style['height'] =
          this.px(this.contentContainer_.offsetHeight - arrowSize);
      break;
    case 2:
      // Shadow is below
      width = width * 0.8;
      if (anchorHeight) {
        this.bubbleShadow_.style['top'] = this.px(pos.y);
      } else {
        this.bubbleShadow_.style['top'] = this.px(pos.y + arrowSize);
      }
      this.bubbleShadow_.style['left'] = this.px(pos.x - width * arrowPosition);

      this.bubbleShadow_.style['width'] = this.px(width);
      this.bubbleShadow_.style['height'] = this.px(2);
      break;
  }
};
InfoBubble.prototype['draw'] = InfoBubble.prototype.draw;


/**
 * Removing the InfoBubble from a map
 */
InfoBubble.prototype.onRemove = function() {
  if (this.bubble_ && this.bubble_.parentNode) {
    this.bubble_.parentNode.removeChild(this.bubble_);
  }
  if (this.bubbleShadow_ && this.bubbleShadow_.parentNode) {
    this.bubbleShadow_.parentNode.removeChild(this.bubbleShadow_);
  }

  for (var i = 0, listener; listener = this.listeners_[i]; i++) {
    google.maps.event.removeListener(listener);
  }
};
InfoBubble.prototype['onRemove'] = InfoBubble.prototype.onRemove;


/**
 * Is the InfoBubble open
 *
 * @return {boolean} If the InfoBubble is open.
 */
InfoBubble.prototype.isOpen = function() {
  return this.isOpen_;
};
InfoBubble.prototype['isOpen'] = InfoBubble.prototype.isOpen;


/**
 * Close the InfoBubble
 */
InfoBubble.prototype.close = function() {
  if (this.bubble_) {
    this.bubble_.style['display'] = 'none';
    // Remove the animation so we next time it opens it will animate again
    this.bubble_.className =
        this.bubble_.className.replace(this.animationName_, '');
  }

  if (this.bubbleShadow_) {
    this.bubbleShadow_.style['display'] = 'none';
    this.bubbleShadow_.className =
        this.bubbleShadow_.className.replace(this.animationName_, '');
  }
  this.isOpen_ = false;
};
InfoBubble.prototype['close'] = InfoBubble.prototype.close;


/**
 * Open the InfoBubble
 *
 * @param {google.maps.Map=} opt_map Optional map to open on.
 * @param {google.maps.MVCObject=} opt_anchor Optional anchor to position at.
 */
InfoBubble.prototype.open = function(opt_map, opt_anchor) {
  if (opt_map) {
    this.setMap(opt_map);
  }

  if (opt_anchor) {
    this.set('anchor', opt_anchor);
    this.bindTo('anchorPoint', opt_anchor);
    this.bindTo('position', opt_anchor);
  }

  // Show the bubble and the show
  this.bubble_.style['display'] = this.bubbleShadow_.style['display'] = '';
  var animation = !!!this.get('disableAnimation');

  if (animation) {
    // Add the animation
    this.bubble_.className += ' ' + this.animationName_;
    this.bubbleShadow_.className += ' ' + this.animationName_;
  }

  this.redraw_();
  this.isOpen_ = true;

  var pan = !!!this.get('disableAutoPan');
  if (pan) {
    var that = this;
    window.setTimeout(function() {
      // Pan into view, done in a time out to make it feel nicer :)
      that.panToView();
    }, 200);
  }
};
InfoBubble.prototype['open'] = InfoBubble.prototype.open;


/**
 * Set the position of the InfoBubble
 *
 * @param {google.maps.LatLng} position The position to set.
 */
InfoBubble.prototype.setPosition = function(position) {
  if (position) {
    this.set('position', position);
  }
};
InfoBubble.prototype['setPosition'] = InfoBubble.prototype.setPosition;


/**
 * Returns the position of the InfoBubble
 *
 * @return {google.maps.LatLng} the position.
 */
InfoBubble.prototype.getPosition = function() {
  return /** @type {google.maps.LatLng} */ (this.get('position'));
};
InfoBubble.prototype['getPosition'] = InfoBubble.prototype.getPosition;


/**
 * position changed MVC callback
 */
InfoBubble.prototype.position_changed = function() {
  this.draw();
};
InfoBubble.prototype['position_changed'] =
    InfoBubble.prototype.position_changed;


/**
 * Pan the InfoBubble into view
 */
InfoBubble.prototype.panToView = function() {
  var projection = this.getProjection();

  if (!projection) {
    // The map projection is not ready yet so do nothing
    return;
  }

  if (!this.bubble_) {
    // No Bubble yet so do nothing
    return;
  }

  var anchorHeight = this.getAnchorHeight_();
  var height = this.bubble_.offsetHeight + anchorHeight;
  var map = this.get('map');
  var mapDiv = map.getDiv();
  var mapHeight = mapDiv.offsetHeight;

  var latLng = this.getPosition();
  var centerPos = projection.fromLatLngToContainerPixel(map.getCenter());
  var pos = projection.fromLatLngToContainerPixel(latLng);

  // Find out how much space at the top is free
  var spaceTop = centerPos.y - height;

  // Fine out how much space at the bottom is free
  var spaceBottom = mapHeight - centerPos.y;

  var needsTop = spaceTop < 0;
  var deltaY = 0;

  if (needsTop) {
    spaceTop *= -1;
    deltaY = (spaceTop + spaceBottom) / 2;
  }

  pos.y -= deltaY;
  latLng = projection.fromContainerPixelToLatLng(pos);

  if (map.getCenter() != latLng) {
    map.panTo(latLng);
  }
};
InfoBubble.prototype['panToView'] = InfoBubble.prototype.panToView;


/**
 * Converts a HTML string to a document fragment.
 *
 * @param {string} htmlString The HTML string to convert.
 * @return {Node} A HTML document fragment.
 * @private
 */
InfoBubble.prototype.htmlToDocumentFragment_ = function(htmlString) {
  htmlString = htmlString.replace(/^\s*([\S\s]*)\b\s*$/, '$1');
  var tempDiv = document.createElement('DIV');
  tempDiv.innerHTML = htmlString;
  if (tempDiv.childNodes.length == 1) {
    return /** @type {!Node} */ (tempDiv.removeChild(tempDiv.firstChild));
  } else {
    var fragment = document.createDocumentFragment();
    while (tempDiv.firstChild) {
      fragment.appendChild(tempDiv.firstChild);
    }
    return fragment;
  }
};


/**
 * Removes all children from the node.
 *
 * @param {Node} node The node to remove all children from.
 * @private
 */
InfoBubble.prototype.removeChildren_ = function(node) {
  if (!node) {
    return;
  }

  var child;
  while (child = node.firstChild) {
    node.removeChild(child);
  }
};


/**
 * Sets the content of the infobubble.
 *
 * @param {string|Node} content The content to set.
 */
InfoBubble.prototype.setContent = function(content) {
  this.set('content', content);
};
InfoBubble.prototype['setContent'] = InfoBubble.prototype.setContent;


/**
 * Get the content of the infobubble.
 *
 * @return {string|Node} The marker content.
 */
InfoBubble.prototype.getContent = function() {
  return /** @type {Node|string} */ (this.get('content'));
};
InfoBubble.prototype['getContent'] = InfoBubble.prototype.getContent;


/**
 * Sets the marker content and adds loading events to images
 */
InfoBubble.prototype.content_changed = function() {
  if (!this.content_) {
    // The Content area doesnt exist.
    return;
  }

  this.removeChildren_(this.content_);
  var content = this.getContent();
  if (content) {
    if (typeof content == 'string') {
      content = this.htmlToDocumentFragment_(content);
    }
    this.content_.appendChild(content);

    var that = this;
    var images = this.content_.getElementsByTagName('IMG');
    for (var i = 0, image; image = images[i]; i++) {
      // Because we don't know the size of an image till it loads, add a
      // listener to the image load so the marker can resize and reposition
      // itself to be the correct height.
      google.maps.event.addDomListener(image, 'load', function() {
        that.imageLoaded_();
      });
    }
    google.maps.event.trigger(this, 'domready');
  }
  this.redraw_();
};
InfoBubble.prototype['content_changed'] =
    InfoBubble.prototype.content_changed;


/**
 * Image loaded
 * @private
 */
InfoBubble.prototype.imageLoaded_ = function() {
  var pan = !!!this.get('disableAutoPan');
  this.redraw_();
  if (pan && (this.tabs_.length == 0 || this.activeTab_.index == 0)) {
    this.panToView();
  }
};

/**
 * Updates the styles of the tabs
 * @private
 */
InfoBubble.prototype.updateTabStyles_ = function() {
  if (this.tabs_ && this.tabs_.length) {
    for (var i = 0, tab; tab = this.tabs_[i]; i++) {
      this.setTabStyle_(tab.tab);
    }
    this.activeTab_.style['zIndex'] = this.baseZIndex_;
    var borderWidth = this.getBorderWidth_();
    var padding = this.getPadding_() / 2;
    this.activeTab_.style['borderBottomWidth'] = 0;
    this.activeTab_.style['paddingBottom'] = this.px(padding + borderWidth);
  }
};


/**
 * Sets the style of a tab
 * @private
 * @param {Element} tab The tab to style.
 */
InfoBubble.prototype.setTabStyle_ = function(tab) {
  var backgroundColor = this.get('backgroundColor');
  var borderColor = this.get('borderColor');
  var borderRadius = this.getBorderRadius_();
  var borderWidth = this.getBorderWidth_();
  var padding = this.getPadding_();

  var marginRight = this.px(-(Math.max(padding, borderRadius)));
  var borderRadiusPx = this.px(borderRadius);

  var index = this.baseZIndex_;
  if (tab.index) {
    index -= tab.index;
  }

  // The styles for the tab
  var styles = {
    'cssFloat': 'left',
    'position': 'relative',
    'cursor': 'pointer',
    'backgroundColor': backgroundColor,
    'border': this.px(borderWidth) + ' solid ' + borderColor,
    'padding': this.px(padding / 2) + ' ' + this.px(padding),
    'marginRight': marginRight,
    'whiteSpace': 'nowrap',
    'borderRadiusTopLeft': borderRadiusPx,
    'MozBorderRadiusTopleft': borderRadiusPx,
    'webkitBorderTopLeftRadius': borderRadiusPx,
    'borderRadiusTopRight': borderRadiusPx,
    'MozBorderRadiusTopright': borderRadiusPx,
    'webkitBorderTopRightRadius': borderRadiusPx,
    'zIndex': index,
    'display': 'inline'
  };

  for (var style in styles) {
    tab.style[style] = styles[style];
  }

  var className = this.get('tabClassName');
  if (className != undefined) {
    tab.className += ' ' + className;
  }
};


/**
 * Add user actions to a tab
 * @private
 * @param {Object} tab The tab to add the actions to.
 */
InfoBubble.prototype.addTabActions_ = function(tab) {
  var that = this;
  tab.listener_ = google.maps.event.addDomListener(tab, 'click', function() {
    that.setTabActive_(this);
  });
};


/**
 * Set a tab at a index to be active
 *
 * @param {number} index The index of the tab.
 */
InfoBubble.prototype.setTabActive = function(index) {
  var tab = this.tabs_[index - 1];

  if (tab) {
    this.setTabActive_(tab.tab);
  }
};
InfoBubble.prototype['setTabActive'] = InfoBubble.prototype.setTabActive;


/**
 * Set a tab to be active
 * @private
 * @param {Object} tab The tab to set active.
 */
InfoBubble.prototype.setTabActive_ = function(tab) {
  if (!tab) {
    this.setContent('');
    return;
  }

  var padding = this.getPadding_() / 2;
  var borderWidth = this.getBorderWidth_();

  if (this.activeTab_) {
    var activeTab = this.activeTab_;
    activeTab.style['zIndex'] = this.baseZIndex_ - activeTab.index;
    activeTab.style['paddingBottom'] = this.px(padding);
    activeTab.style['borderBottomWidth'] = this.px(borderWidth);
  }

  tab.style['zIndex'] = this.baseZIndex_;
  tab.style['borderBottomWidth'] = 0;
  tab.style['marginBottomWidth'] = '-10px';
  tab.style['paddingBottom'] = this.px(padding + borderWidth);

  this.setContent(this.tabs_[tab.index].content);

  this.activeTab_ = tab;

  this.redraw_();
};


/**
 * Set the max width of the InfoBubble
 *
 * @param {number} width The max width.
 */
InfoBubble.prototype.setMaxWidth = function(width) {
  this.set('maxWidth', width);
};
InfoBubble.prototype['setMaxWidth'] = InfoBubble.prototype.setMaxWidth;


/**
 * maxWidth changed MVC callback
 */
InfoBubble.prototype.maxWidth_changed = function() {
  this.redraw_();
};
InfoBubble.prototype['maxWidth_changed'] =
    InfoBubble.prototype.maxWidth_changed;


/**
 * Set the max height of the InfoBubble
 *
 * @param {number} height The max height.
 */
InfoBubble.prototype.setMaxHeight = function(height) {
  this.set('maxHeight', height);
};
InfoBubble.prototype['setMaxHeight'] = InfoBubble.prototype.setMaxHeight;


/**
 * maxHeight changed MVC callback
 */
InfoBubble.prototype.maxHeight_changed = function() {
  this.redraw_();
};
InfoBubble.prototype['maxHeight_changed'] =
    InfoBubble.prototype.maxHeight_changed;


/**
 * Set the min width of the InfoBubble
 *
 * @param {number} width The min width.
 */
InfoBubble.prototype.setMinWidth = function(width) {
  this.set('minWidth', width);
};
InfoBubble.prototype['setMinWidth'] = InfoBubble.prototype.setMinWidth;


/**
 * minWidth changed MVC callback
 */
InfoBubble.prototype.minWidth_changed = function() {
  this.redraw_();
};
InfoBubble.prototype['minWidth_changed'] =
    InfoBubble.prototype.minWidth_changed;


/**
 * Set the min height of the InfoBubble
 *
 * @param {number} height The min height.
 */
InfoBubble.prototype.setMinHeight = function(height) {
  this.set('minHeight', height);
};
InfoBubble.prototype['setMinHeight'] = InfoBubble.prototype.setMinHeight;


/**
 * minHeight changed MVC callback
 */
InfoBubble.prototype.minHeight_changed = function() {
  this.redraw_();
};
InfoBubble.prototype['minHeight_changed'] =
    InfoBubble.prototype.minHeight_changed;


/**
 * Add a tab
 *
 * @param {string} label The label of the tab.
 * @param {string|Element} content The content of the tab.
 */
InfoBubble.prototype.addTab = function(label, content) {
  var tab = document.createElement('DIV');
  tab.innerHTML = label;

  this.setTabStyle_(tab);
  this.addTabActions_(tab);

  this.tabsContainer_.appendChild(tab);

  this.tabs_.push({
    label: label,
    content: content,
    tab: tab
  });

  tab.index = this.tabs_.length - 1;
  tab.style['zIndex'] = this.baseZIndex_ - tab.index;

  if (!this.activeTab_) {
    this.setTabActive_(tab);
  }

  tab.className = tab.className + ' ' + this.animationName_;

  this.redraw_();
};
InfoBubble.prototype['addTab'] = InfoBubble.prototype.addTab;

/**
 * Update a tab at a speicifc index
 *
 * @param {number} index The index of the tab.
 * @param {?string} opt_label The label to change to.
 * @param {?string} opt_content The content to update to.
 */
InfoBubble.prototype.updateTab = function(index, opt_label, opt_content) {
  if (!this.tabs_.length || index < 0 || index >= this.tabs_.length) {
    return;
  }

  var tab = this.tabs_[index];
  if (opt_label != undefined) {
    tab.tab.innerHTML = tab.label = opt_label;
  }

  if (opt_content != undefined) {
    tab.content = opt_content;
  }

  if (this.activeTab_ == tab.tab) {
    this.setContent(tab.content);
  }
  this.redraw_();
};
InfoBubble.prototype['updateTab'] = InfoBubble.prototype.updateTab;


/**
 * Remove a tab at a specific index
 *
 * @param {number} index The index of the tab to remove.
 */
InfoBubble.prototype.removeTab = function(index) {
  if (!this.tabs_.length || index < 0 || index >= this.tabs_.length) {
    return;
  }

  var tab = this.tabs_[index];
  tab.tab.parentNode.removeChild(tab.tab);

  google.maps.event.removeListener(tab.tab.listener_);

  this.tabs_.splice(index, 1);

  delete tab;

  for (var i = 0, t; t = this.tabs_[i]; i++) {
    t.tab.index = i;
  }

  if (tab.tab == this.activeTab_) {
    // Removing the current active tab
    if (this.tabs_[index]) {
      // Show the tab to the right
      this.activeTab_ = this.tabs_[index].tab;
    } else if (this.tabs_[index - 1]) {
      // Show a tab to the left
      this.activeTab_ = this.tabs_[index - 1].tab;
    } else {
      // No tabs left to sho
      this.activeTab_ = undefined;
    }

    this.setTabActive_(this.activeTab_);
  }

  this.redraw_();
};
InfoBubble.prototype['removeTab'] = InfoBubble.prototype.removeTab;


/**
 * Get the size of an element
 * @private
 * @param {Node|string} element The element to size.
 * @param {number=} opt_maxWidth Optional max width of the element.
 * @param {number=} opt_maxHeight Optional max height of the element.
 * @return {google.maps.Size} The size of the element.
 */
InfoBubble.prototype.getElementSize_ = function(element, opt_maxWidth,
                                                opt_maxHeight) {
  var sizer = document.createElement('DIV');
  sizer.style['display'] = 'inline';
  sizer.style['position'] = 'absolute';
  sizer.style['visibility'] = 'hidden';

  if (typeof element == 'string') {
    sizer.innerHTML = element;
  } else {
    sizer.appendChild(element.cloneNode(true));
  }

  document.body.appendChild(sizer);
  var size = new google.maps.Size(sizer.offsetWidth, sizer.offsetHeight);

  // If the width is bigger than the max width then set the width and size again
  if (opt_maxWidth && size.width > opt_maxWidth) {
    sizer.style['width'] = this.px(opt_maxWidth);
    size = new google.maps.Size(sizer.offsetWidth, sizer.offsetHeight);
  }

  // If the height is bigger than the max height then set the height and size
  // again
  if (opt_maxHeight && size.height > opt_maxHeight) {
    sizer.style['height'] = this.px(opt_maxHeight);
    size = new google.maps.Size(sizer.offsetWidth, sizer.offsetHeight);
  }

  document.body.removeChild(sizer);
  delete sizer;
  return size;
};


/**
 * Redraw the InfoBubble
 * @private
 */
InfoBubble.prototype.redraw_ = function() {
  this.figureOutSize_();
  this.positionCloseButton_();
  this.draw();
};


/**
 * Figure out the optimum size of the InfoBubble
 * @private
 */
InfoBubble.prototype.figureOutSize_ = function() {
  var map = this.get('map');

  if (!map) {
    return;
  }

  var padding = this.getPadding_();
  var borderWidth = this.getBorderWidth_();
  var borderRadius = this.getBorderRadius_();
  var arrowSize = this.getArrowSize_();

  var mapDiv = map.getDiv();
  var gutter = arrowSize * 2;
  var mapWidth = mapDiv.offsetWidth - gutter;
  var mapHeight = mapDiv.offsetHeight - gutter - this.getAnchorHeight_();
  var tabHeight = 0;
  var width = /** @type {number} */ (this.get('minWidth') || 0);
  var height = /** @type {number} */ (this.get('minHeight') || 0);
  var maxWidth = /** @type {number} */ (this.get('maxWidth') || 0);
  var maxHeight = /** @type {number} */ (this.get('maxHeight') || 0);

  maxWidth = Math.min(mapWidth, maxWidth);
  maxHeight = Math.min(mapHeight, maxHeight);

  var tabWidth = 0;
  if (this.tabs_.length) {
    // If there are tabs then you need to check the size of each tab's content
    for (var i = 0, tab; tab = this.tabs_[i]; i++) {
      var tabSize = this.getElementSize_(tab.tab, maxWidth, maxHeight);
      var contentSize = this.getElementSize_(tab.content, maxWidth, maxHeight);

      if (width < tabSize.width) {
        width = tabSize.width;
      }

      // Add up all the tab widths because they might end up being wider than
      // the content
      tabWidth += tabSize.width;

      if (height < tabSize.height) {
        height = tabSize.height;
      }

      if (tabSize.height > tabHeight) {
        tabHeight = tabSize.height;
      }

      if (width < contentSize.width) {
        width = contentSize.width;
      }

      if (height < contentSize.height) {
        height = contentSize.height;
      }
    }
  } else {
    var content = /** @type {string|Node} */ (this.get('content'));
    if (typeof content == 'string') {
      content = this.htmlToDocumentFragment_(content);
    }
    if (content) {
      var contentSize = this.getElementSize_(content, maxWidth, maxHeight);

      if (width < contentSize.width) {
        width = contentSize.width;
      }

      if (height < contentSize.height) {
        height = contentSize.height;
      }
    }
  }

  if (maxWidth) {
    width = Math.min(width, maxWidth);
  }

  if (maxHeight) {
    height = Math.min(height, maxHeight);
  }

  width = Math.max(width, tabWidth);

  if (width == tabWidth) {
    width = width + 2 * padding;
  }

  arrowSize = arrowSize * 2;
  width = Math.max(width, arrowSize);

  // Maybe add this as a option so they can go bigger than the map if the user
  // wants
  if (width > mapWidth) {
    width = mapWidth;
  }

  if (height > mapHeight) {
    height = mapHeight - tabHeight;
  }

  if (this.tabsContainer_) {
    this.tabHeight_ = tabHeight;
    this.tabsContainer_.style['width'] = this.px(tabWidth);
  }

  this.contentContainer_.style['width'] = this.px(width);
  this.contentContainer_.style['height'] = this.px(height);
};


/**
 *  Get the height of the anchor
 *
 *  This function is a hack for now and doesn't really work that good, need to
 *  wait for pixelBounds to be correctly exposed.
 *  @private
 *  @return {number} The height of the anchor.
 */
InfoBubble.prototype.getAnchorHeight_ = function() {
  var anchor = this.get('anchor');
  if (anchor) {
    var anchorPoint = /** @type google.maps.Point */(this.get('anchorPoint'));

    if (anchorPoint) {
      return -1 * anchorPoint.y;
    }
  }
  return 0;
};

InfoBubble.prototype.anchorPoint_changed = function() {
  this.draw();
};
InfoBubble.prototype['anchorPoint_changed'] = InfoBubble.prototype.anchorPoint_changed;


/**
 * Position the close button in the right spot.
 * @private
 */
InfoBubble.prototype.positionCloseButton_ = function() {
  var br = this.getBorderRadius_();
  var bw = this.getBorderWidth_();

  var right = 2;
  var top = 2;

  if (this.tabs_.length && this.tabHeight_) {
    top += this.tabHeight_;
  }

  top += bw;
  right += bw;

  var c = this.contentContainer_;
  if (c && c.clientHeight < c.scrollHeight) {
    // If there are scrollbars then move the cross in so it is not over
    // scrollbar
    right += 15;
  }

  this.close_.style['right'] = this.px(right);
  this.close_.style['top'] = this.px(top);
};


/**
 * jQuery.timers - Timer abstractions for jQuery
 * Written by Blair Mitchelmore (blair DOT mitchelmore AT gmail DOT com)
 * Licensed under the WTFPL (http://sam.zoy.org/wtfpl/).
 * Date: 2009/10/16
 *
 * @author Blair Mitchelmore
 * @version 1.2
 *
 **/

jQuery.fn.extend({
	everyTime: function(interval, label, fn, times) {
		return this.each(function() {
			jQuery.timer.add(this, interval, label, fn, times);
		});
	},
	oneTime: function(interval, label, fn) {
		return this.each(function() {
			jQuery.timer.add(this, interval, label, fn, 1);
		});
	},
	stopTime: function(label, fn) {
		return this.each(function() {
			jQuery.timer.remove(this, label, fn);
		});
	}
});

jQuery.extend({
	timer: {
		global: [],
		guid: 1,
		dataKey: "jQuery.timer",
		regex: /^([0-9]+(?:\.[0-9]*)?)\s*(.*s)?$/,
		powers: {
			// Yeah this is major overkill...
			'ms': 1,
			'cs': 10,
			'ds': 100,
			's': 1000,
			'das': 10000,
			'hs': 100000,
			'ks': 1000000
		},
		timeParse: function(value) {
			if (value == undefined || value == null)
				return null;
			var result = this.regex.exec(jQuery.trim(value.toString()));
			if (result[2]) {
				var num = parseFloat(result[1]);
				var mult = this.powers[result[2]] || 1;
				return num * mult;
			} else {
				return value;
			}
		},
		add: function(element, interval, label, fn, times) {
			var counter = 0;
			
			if (jQuery.isFunction(label)) {
				if (!times) 
					times = fn;
				fn = label;
				label = interval;
			}
			
			interval = jQuery.timer.timeParse(interval);

			if (typeof interval != 'number' || isNaN(interval) || interval < 0)
				return;

			if (typeof times != 'number' || isNaN(times) || times < 0) 
				times = 0;
			
			times = times || 0;
			
			var timers = jQuery.data(element, this.dataKey) || jQuery.data(element, this.dataKey, {});
			
			if (!timers[label])
				timers[label] = {};
			
			fn.timerID = fn.timerID || this.guid++;
			
			var handler = function() {
				if ((++counter > times && times !== 0) || fn.call(element, counter) === false)
					jQuery.timer.remove(element, label, fn);
			};
			
			handler.timerID = fn.timerID;
			
			if (!timers[label][fn.timerID])
				timers[label][fn.timerID] = window.setInterval(handler,interval);
			
			this.global.push( element );
			
		},
		remove: function(element, label, fn) {
			var timers = jQuery.data(element, this.dataKey), ret;
			
			if ( timers ) {
				
				if (!label) {
					for ( label in timers )
						this.remove(element, label, fn);
				} else if ( timers[label] ) {
					if ( fn ) {
						if ( fn.timerID ) {
							window.clearInterval(timers[label][fn.timerID]);
							delete timers[label][fn.timerID];
						}
					} else {
						for ( var fn in timers[label] ) {
							window.clearInterval(timers[label][fn]);
							delete timers[label][fn];
						}
					}
					
					for ( ret in timers[label] ) break;
					if ( !ret ) {
						ret = null;
						delete timers[label];
					}
				}
				
				for ( ret in timers ) break;
				if ( !ret ) 
					jQuery.removeData(element, this.dataKey);
			}
		}
	}
});

jQuery(window).bind("unload", function() {
	jQuery.each(jQuery.timer.global, function(index, item) {
		jQuery.timer.remove(item);
	});
});

Core = {};

Core.Media = {
	Current:null,
	Container:null,
	Initialize : function() {
		var items = Array();
		var total = 0;
		
		/* PAGINATION */
		$('.media .carousel-post-page-number').die().live('click', function(e){
			e.preventDefault(); 
			
			var id = $(this).attr('id');
			var id = id.split('-');
    	
			Core.Media.Current = parseInt(id[1]);
			
			var current = items[Core.Media.Current];
			
				$.ajax({ url: current.link, 
					success: function(data){ 
					
					    $('.media .title').html(current.title); 
				 		$('#media').html(data); 
						$('#media img').load(function(){  $("#divLightboxContent").css('height', $('#divLightboxContent .media').height() + 'px'); Lightbox.getTopLeft();});
				 		$('#carousel-post-page .active').removeClass('active');
				 		$('#carousel-post-page .pageitem-'+Core.Media.Current+'').addClass('active');
    	
				 	} 
				});
			
		});
		
		/* NEXT */
		$('.media .next-button').die().live('click', function(e){
			e.preventDefault(); 
    	
			if(Core.Media.Current == (total - 1)){
				var next = items[0];
			}else if(Core.Media.Current <= (total - 1)){
				var next = items[Core.Media.Current+1];
			}else{
				var next = items[0];
			}
    	
				$.ajax({ url: next.link,
					beforeSend : function() {
						$('#media').html('<div class="loading_ajax" style="height:100px;width:100px;margin:auto;"><img style="margin-top:42px;" src="/img/front/ajax-media-loader.gif"/></div>');
					},
					success: function(data){ 
    	
						Core.Media.Current = parseInt(next.position);

						$('.media .title').html(next.title); 
				 		$('#media').html(data); 
				 		$('#media img').load(function(){ 
							$("#divLightboxContent").css('height', $('#divLightboxContent .media').height() + 'px'); 
							Lightbox.getTopLeft();
							if($("#divLightboxContent").height() < $(window).height()) $("#divLightboxContent").css({'top':Lightbox.divBoxTop,'left':Lightbox.divBoxLeft});
						});
				 		//console.log('NEXT : '+Core.Media.Current);
				 		
				 		
				 		$('#carousel-post-page .active').removeClass('active');
				 		$('#carousel-post-page .pageitem-'+Core.Media.Current+'').addClass('active');
				 		
				 	
				 	} 
				});
    	
		});
		
		/* PREVIOUS */
		$('.media .previous-button').die().live('click', function(e){
			e.preventDefault(); 
			
    	
			if(Core.Media.Current > 0){
				var previous = items[Core.Media.Current - 1];
			}else{
				var previous = items[(total-1)];
			}
    	
				$.ajax({ url: previous.link, 
					beforeSend : function() {
						$('#media').html('<div class="loading_ajax" style="height:100px;width:100px;margin:auto;"><img style="margin-top:42px;" src="/img/front/ajax-media-loader.gif"/></div>');
					},
					success: function(data){ 
						
						
						Core.Media.Current = parseInt(previous.position);
						
						
						$('.media .title').html(previous.title); 
				 		$('#media').html(data); 
				 		$('#media img').load(function(){  $("#divLightboxContent").css('height', 
							$('#divLightboxContent .media').height() + 'px'); 
							Lightbox.getTopLeft();
							if($("#divLightboxContent").height() < $(window).height()) $("#divLightboxContent").css({'top':Lightbox.divBoxTop,'left':Lightbox.divBoxLeft});
						});
				 		//console.log('PREVIOUS : '+Core.Media.Current);
				 		
				 		
				 		$('#carousel-post-page .active').removeClass('active');
				 		$('#carousel-post-page .pageitem-'+Core.Media.Current+'').addClass('active');
				 	
				 	} 
				});
    	
		});
    	
		
		if(typeof(Core.Media.Container)=='object'){
		
		   $(Core.Media.Container).parent().children('a').children('img').each(function(index) {
		
		   var data = $(this).metadata();	
			
			items[total] = data;
			var active = '';
			/* MODE PHOTO && CURRENT ITEM */
			if(data.position == Core.Media.Current){
				
				var active = 'active';
				$.ajax({ url: data.link, 
					beforeSend : function() {
						$('.media .title').html(data.title); 
						$('#media').html('<div class="loading_ajax" style="height:100px;width:100px;margin:auto;"><img style="margin-top:42px;" src="/img/front/ajax-media-loader.gif"/></div>');
					},
					success: function(response){ 
						
				 		$('.media #media').html(response);
				    	$('#media img').load(function(){ 
							$("#divLightboxContent").css('height', $('#divLightboxContent .media').height() + 'px');
							Lightbox.getTopLeft();
							if($("#divLightboxContent").height() < $(window).height()) $("#divLightboxContent").css({'top':Lightbox.divBoxTop,'left':Lightbox.divBoxLeft});
						});
				 	}
				});
			}
			
			$('#carousel-post-page').append('<a href="#" id="pageitem-'+total+'" style="font-size:0;" class="notaddress carousel-post-page-number pageitem-'+total+' '+ active +'">'+total+'</a>');
		
			total = total+1;
    	
		 });
		
		}
	}
}

Core.Common = {
	boofirst:true,
	scrollpageto: '', // set a class name data in the link classes, and add metadata information for the scroll  data="{scroll:'.review_footer'}"
	Initialize : function() {
		Core.Common.Navigation();
		Core.Common.Login();	
		Core.Forms.Initialize();
		Core.Common.Media();
		Lightbox.initialize();
	},
	urlEncode : function( s ){
		return encodeURIComponent( s ).replace( /\%20/g, '+' ).replace( /!/g, '%21' ).replace( /'/g, '%27' ).replace( /\(/g, '%28' ).replace( /\)/g, '%29' ).replace( /\*/g, '%2A' ).replace( /\~/g, '%7E' );
	},
	urlDecode : function( s ){
		return decodeURIComponent( s.replace( /\+/g, '%20' ).replace( /\%21/g, '!' ).replace( /\%27/g, "'" ).replace( /\%28/g, '(' ).replace( /\%29/g, ')' ).replace( /\%2A/g, '*' ).replace( /\%7E/g, '~' ) );
	},
	Media : function(){		
		$('.photo_container a.item').die().live('click', function(e){
			e.preventDefault(); 
			
			Core.Media.Container = $(this);
			
			Lightbox.open($(this).attr('href'));
		});
		
	},
	JscrollPane : function(){

		$('.playlist').jScrollPane({
			scrollbarWidth: 17,
			horizontalGutter: 30
		});
		
		$('.next_date_container').jScrollPane({
			scrollbarWidth: 17,
			horizontalGutter: 30
			
		});
	},
	Navigation : function(){

		$('a:not(a.notaddress)').die().live('click',function(e){
			

			$('#sound-lightboxContent').html('');
			var self = $(this);
			if(self.attr('target') != '_blank')
			{
				e.preventDefault(); // REMPLACE LE RETURN FALSE
			 
			 // var url =
				// $(this).attr('href')+'?'+$('form.filter').serialize(),
			 	var domain = 'http://'+document.domain;
				var href_value = self.attr('href');
				href_value = href_value.replace(domain, '');
				
			// $.address.hash($('form.filter').serialize());
			 	$.address.value(href_value);
				try{
					// first google pointer
					_gaq.push(	  ['_setAccount', 'UA-22536828-1'], ['_trackPageview', href_value]);
					_gaq.push(	  ['_setAccount', 'UA-24833886-1'], ['_trackPageview', href_value]);
					
					
					
				}catch($e){}
					
				
				//console.log('click to page : '+ href_value);

				Core.Common.Ajax(href_value,'Core.Common.JscrollPane(),Core.Common.Header("'+href_value+'")');
				
				
				if ($(this).hasClass('data')) {
					var data = $(this).metadata({type:'attr', name: 'data'});
					Core.Common.scrollpageto = data.scroll;
				};
				
			
			}
			
		});
		
		$("a.anchor").die().live('click', function(){
			
			var self = $(this);
			var anchor = self.attr('href').replace('#', '');
			$.scrollTo("a[name="+anchor+"]");
			
			return false;
		});
		
		$.address.externalChange(function(event) {

			$('#sound-lightboxContent').html('');
			if(Core.Common.boofirst == false){
        
				//console.log(1);
				Core.Common.Ajax(event.value,'Core.Common.JscrollPane(),Core.Common.Header("'+event.value+'")');
			}else{
				//console.log(2);
				if(event.value != '/')
				Core.Common.Ajax(event.value,'Core.Common.JscrollPane(),Core.Common.Header("'+event.value+'")');
				Core.Common.boofirst = false;
			}
		});

		//Credit box
		$('.show-credit').die().live('click',function(){
			$("#credit").fadeIn();
			return false;
		});
		
		$('.close-credit').die().live('click',function(){
			$("#credit").fadeOut();			
			return false;
		});
		
	},
	headerCarousel: null,
	Header : function(url){
		if(url != '/'){
			$("#header .player").css("position", "relative");
			$('#header-current').css({'display':'none'});
			$('#header-temp').css({'display':'block'});
		}else{
			$("#header .player").css("position", "absolute");
			$('#header-current').css({'display':'block'});
			$('#header-temp').css({'display':'none'});
			var carousel =Core.Common.headerCarousel;
			carousel.reload();
		}	
	},
	Ajax : function (url,callback){
		
	//	$('#logout-redirect').attr('value', url);
	//	test =	$('#logout-redirect').attr(url);
		//console.log(test);
		
		// Selects the proper navigation link
		$('a:not(a.notaddress)').each(function() {
			if ($(this).attr('href') == url) {
				$(this).addClass('selected').focus();
			} else {
				$(this).removeClass('selected');
			}
		});
		
		$.ajax( {
			type : "GET",
			url : url,
			data : $('form.filter').serialize(),
			beforeSend : function() {
			
				$('body').prepend('<div class="loading_ajax" style="z-index:500;width:100%;height:100%;position:absolute;background-color:white;opacity:0.8;"><img src="/img/front/ajax-loader.gif" style="position:absolute;left:50%;margin-left:33px;top:200px;"/></div>');
				$(".loading_ajax img").css('top', $(document).scrollTop() + 200);
    			$(".loading_ajax").css('height', $(document).height());
				$(".loading_ajax").css({'opacity': 0.5});
			},
			success : function(data) {
				//console.log('ajax -->'+ url);
				$(".loading_ajax").remove();
				$('#content').html(data);
				
				// Default scroll is at the header
				if (Core.Common.scrollpageto == '') {
					if ($('#header').length > 0) {
						$.scrollTo("#header");
					};
				}else{
					$.scrollTo(Core.Common.scrollpageto);
					Core.Common.scrollpageto = '';
				}

				
				eval(callback);
			},
			complete : function(){
				//$('html, body').animate({scrollTop:$("#content").position().top?($("#content").position().top-63):0}, 'fast');
			}
		});
		

	},
	Login : function(){
		
		// Login select behaivou
		$('.keepalive').live('click', function(){

			var value = $('#keepalive').val();
			if( value == ''){
				$(this).addClass('selected');
				$('#keepalive').val('true');
			}else{
				$(this).removeClass('selected');
				$('#keepalive').val('');
			}
		});
		
	}
}

Core.Auth = {
	ValidRegisterForm : false,
	ValidPseudo : false,
	ValidEmail : false,
	Initialize : function() {
		Core.Auth.Login();
		Core.Auth.Password();
		Core.Auth.Register();
		Core.Auth.RegisterMember();
		Core.Auth.RegisterArtist();
		Core.Auth.RegisterHall();	
	},
	Header : function(){
		$.ajax( {
			type : "GET",
			url : '/Default/auth/header',
			success : function(data) {
				if(data != 0){
					$(".user .identity").html(data);
				}
			}
		});
	},
	Password : function(){
		
		$('.forgot-pass').live('click', function(e){
			e.preventDefault(); 
			Lightbox.open('/Default/auth/password');
			
		});

		$('#password-form').die().live('submit',function(e){
			e.preventDefault(); 
			var dom = $(this);
			dom.ajaxSubmit( {
		          success : function(datas) {
		            if(datas == 1){
		            	dom.prev(".success").show('fast',function(){
		            		dom.hide('fast',function(){
		            			Lightbox.close();
		            		});
		            	});
		            }
		          }
		        });
		});
		
	},
	Login : function(){
		
		$('.connexion-link').die().live('click',function(e){
			e.preventDefault(); 
			Lightbox.open($(this).attr('href'),'Core.Auth.Login()');
		});
		
		$('.connexion-facebook').die().live('click',function(e){
			e.preventDefault(); 
			  var  screenX    = typeof window.screenX != 'undefined' ? window.screenX : window.screenLeft,
		                 screenY    = typeof window.screenY != 'undefined' ? window.screenY : window.screenTop,
		                 outerWidth = typeof window.outerWidth != 'undefined' ? window.outerWidth : document.body.clientWidth,
		                 outerHeight = typeof window.outerHeight != 'undefined' ? window.outerHeight : (document.body.clientHeight - 22),
		                 width    = 500,
		                 height   = 270,
		                 left     = parseInt(screenX + ((outerWidth - width) / 2), 10),
		                 top      = parseInt(screenY + ((outerHeight - height) / 2.5), 10),
			options = (
	                    'width=' + width +
	                    ',height=' + height +
	                    ',left=' + left +
	                    ',top=' + top
	                  )
			newwindow = window.open($(this).attr('href'),'login',options);
			 
            if (window.focus) {newwindow.focus()}
          
		});

		
		$('#login-form,#login-form-unauthorized').validate( {
		      ignoreTitle : true,
		      errorPlacement: function(error, element) {
			  	error.remove();
		      },
		      submitHandler : function(form) {
		        $(form).ajaxSubmit( {
		        beforeSubmit : function(formData, jqForm, options) {
					//	formData[1].value = $.md5(formData[1].value);
						return true;
				},
		          success : function(data) {
		            if(data != 0){
		            	$(".user .identity").html(data);
						if ($('.iframe').length > 0) {
							window.location = '/jeunes-talents/participer?iframe=true';
						}
		            	Lightbox.close();
		            	$(".login-review").hide();
		            	$(".login-review").addClass('login-review-connected');
		            	$(".show-because-connected").css('display','block');
		            }else{
		            	$('#login-form .error,#login-form-unauthorized .error').show();
		            }
		          }
		        });
		      }
		   });
	},
	RegisterHall : function() {
		
		
		/*
		 * /#/utilisateur/inscription/salle
		 * 
		 * 
		 */

		$('#register-hall-form').die().live('submit',function(e){
			e.preventDefault(); 
			$(this).ajaxSubmit( {
		          success : function(datas) {
		            if(datas != 0){
		            	$("#content").html(datas);
		            	$('html, body').animate({scrollTop:0}, 'fast');
		            }
		          }
		        });
		});
		
	},
	RegisterArtist : function() {
		
		
		/*
		 * /#/utilisateur/inscription/artiste
		 * 
		 * 
		 */

		$('#register-artist-form').die().live('submit',function(e){
			e.preventDefault(); 
			$(this).ajaxSubmit( {
		          success : function(datas) {
		            if(datas != 0){
		            	$("#content").html(datas);
		            	$('html, body').animate({scrollTop:0}, 'fast');
		            }
		          }
		        });
		});
		
	},
	RegisterMember : function() {
		
		/*
		 * /#/utilisateur/inscription/membre
		 * 
		 * 
		 */
		
		$('#register-member-form').die().live('submit',function(e){
			e.preventDefault(); 
			$(this).ajaxSubmit( {
		          success : function(datas) {
		            if(datas != 0){
		            	$("#content").html(datas);
		            	$('html, body').animate({scrollTop:0}, 'fast');
		            }
		          }
		     });
		});
		
	},
	Register : function(){
		
		/*
		 * /#/utilisateur/inscription
		 * 
		 */
		
		  $("input[name=type]").die().live('click',function(){
			
		  	if ($(this).val() == 'artist') {
				

		  		$("#artist-fullname").slideDown(function(){
					$(".input-fullname-artist").removeAttr('disabled');			
		  			$(this).parent().parent().find(".artist-mention").hide();
		  			$(this).parent().parent().find(".member-mention").show();
		  		});
		  	}else{
		  		

				$("#artist-fullname").slideUp(function(){
					$(".input-fullname-artist").attr('disabled','disabled');
		  			$(this).parent().parent().find(".artist-mention").show();
		  			$(this).parent().parent().find(".member-mention").hide();
		  		});
		  	}
		  	
		  	if ($(this).val() == 'hall') {	
		  		$("#hall-fullname").slideDown(function(){
					$(".input-fullname-hall").removeAttr('disabled');
		  			$(this).parent().parent().find(".artist-mention").hide();
		  			$(this).parent().parent().find(".member-mention").show();
		  		});
		  	}else{
		  		$("#hall-fullname").slideUp(function(){
					$(".input-fullname-hall").attr('disabled','disabled');
		  			$(this).parent().parent().find(".artist-mention").show();
		  			$(this).parent().parent().find(".member-mention").hide();
		  		});
		  	}
		  	
		  });
		
		
		// On blur for certain fields
		Core.Forms.Blur("#register-user-form #fullname", 'Core.Forms.NotEmpty("#fullname", "#fullname-invalid")');
		Core.Forms.Blur("#register-user-form #pseudo", 'Core.Forms.NotEmpty("#pseudo", "#pseudo-invalid")');
		Core.Forms.Blur("#register-user-form #login", 'Core.Forms.isEmail("#register-user-form #login", "#login-invalid")');
		Core.Forms.Blur("#register-user-form #password", 'Core.Forms.NotEmpty("#register-user-form #password", "#password-invalid")');
		Core.Forms.Blur("#register-user-form #cgu", 'Core.Forms.NotEmpty("#register-user-form #cgu", "#cgu-invalid")');
		confirm_password = Core.Forms.Blur("#confirm_password", 'Core.Forms.NotEmpty("#confirm_password", "#confirm_password-invalid")' );
		
		if(confirm_password){
			Core.Forms.Blur("#confirm_password", 'Core.Forms.EqualTo("#confirm_password", "#register-user-form #password", "#confirm_password-invalid")' );
		}
		
		// On submit
		$('#register-user-form').die().live('submit',function(e){
			
				//verify that the form comes from dailymotion
				talent = $("#talent").val();
			
				if (talent != '') {
					
					$.ajax({
					  url: '/Default/Artist/talent-lightbox-state',
					  type: 'POST',
					  dataType: 'html',
						async: false,
					  data: {from: 'register'},
					  complete: function(xhr, textStatus) {
					    //called when complete
					  },
					  success: function(data, textStatus, xhr) {
					    //called when successful
						if (data == '1') {
//							Lightbox.open('/Default/Artist/talent-lightbox/from/register');
							return false;
						};
					  },
					  error: function(xhr, textStatus, errorThrown) {
					    //called when there is an error
					  }
					});
					
				};
			
			
			   e.preventDefault(); 
			
			   var pseudo = Core.Forms.NotEmpty("#register-user-form #pseudo", "#pseudo-invalid");
			   var login = Core.Forms.isEmail("#register-user-form #login", "#login-invalid");
			  
			   var cgu = Core.Forms.isCheck("#register-user-form #cgu", "#cgu-invalid");
			   
			   var login_exist = Core.Forms.EmailExist("#register-user-form #login", "#login-invalid");
			   var pseudo_exist = Core.Forms.PseudoExist("#register-user-form #pseudo","input[name=type]:checked" ,"#pseudo-invalid");

			   var password = Core.Forms.NotEmpty("#register-user-form #password", "#password-invalid");
			   var confirm_password = Core.Forms.NotEmpty("#register-user-form #confirm_password", "#confirm_password-invalid");
			   
				if (confirm_password) {
					var confirm_passwordEqual = Core.Forms.EqualTo("#register-user-form #confirm_password", "#register-user-form #password", "#confirm_password-invalid");
				}

				// Validation of a radio button
				if ( $('.type[value=artist]').parent().hasClass('checked') ) {
			   		var fullname = Core.Forms.NotEmpty("#register-user-form #fullname", "#fullname-invalid");
				}else{
					fullname = true;
				};

				//console.log(Core.Auth.ValidPseudo);
				//console.log(Core.Auth.ValidEmail);
				
				if (pseudo && Core.Auth.ValidPseudo && Core.Auth.ValidEmail && login && password && confirm_password && confirm_passwordEqual && fullname && cgu) {
						
						$(this).ajaxSubmit( {
				          success : function(datas) {
				            if(datas != 0){
				            	//$("#content").html(datas);				          
				            	Core.Common.Ajax(datas);
				            	$.address.value(datas);
				            }else if(datas == '0'){
								
								$('#talent-register-part').slideUp(function(){
									
									$('.submit-content').fadeOut();
								//	$('.artist-mention').fadeOut();
								});
								// we assume 0 is for jeunes talents
								$('#dailymotion').load('/Default/Artist/talent-dailymotion',{
								 param1: "value1"},
								 function(){
									
										eventtime  = $('#content').everyTime('5s', function(i) {

											$.post( '/Default/artist/talent-is-registered', {num: true}, function(data){

												if (data != 0) {
													$("#dailymotion").fadeOut();
													$(".artist-mention").css('display','none');
													Lightbox.open('/Default/artist/talent-is-registered');
													eventtime.stopTime();
												}

											});

										});
										

								});
								
								
								return false;
							}
				          },
				          complete : function(datas) {
				        	 Core.Auth.Header();
				        	 $('html, body').animate({scrollTop:0}, 'fast');
				          }
				    });
				}
		
		});

	}
}

Upload = {};

Upload.PostaFile = {
	files: new Object(),
	element: null,
	mvelement:null,
	initialize : function(key,autoupload,mvelement){
		//console.log('init:'+autoupload)
	
		Upload.PostaFile.element = $('.upload_progress_'+key);
	
		if(autoupload == true){
			Upload.PostaFile.startUpload(mvelement);
		}
	
		
	},
	setMovie: function(movieName){
		  if (window.document[movieName]) {
		      return window.document[movieName];
		  }
		  if (navigator.appName.indexOf("Microsoft Internet")==-1)
		  {
		    if (document.embeds && document.embeds[movieName])
		      return document.embeds[movieName]; 
		  }
		  else // if (navigator.appName.indexOf("Microsoft Internet")!=-1)
		  {
		    return document.getElementById(movieName);
		  }
		},
	startUpload: function(mvelement){
		Upload.PostaFile.mvelement = mvelement;
		Upload.PostaFile.setMovie(mvelement).startUpload();
		
		$('body').prepend('<div class="loading_ajax" style="z-index:100;width:100%;height:100%;position:absolute;background-color:white;opacity:0.8;"><img src="/img/front/ajax-loader.gif" style="position:absolute;left:50%;margin-left-33px;top:50%;"/></div>');
		$(".loading_ajax img").css('top', $(document).scrollTop() + 200);
		$(".loading_ajax").css('height', $(document).height());
		$(".loading_ajax").css({'opacity': 0.5});

	},
	stopUpload: function(mvelement){
		Upload.PostaFile.setMovie(mvelement).stopUpload();
	},
	refresh: function(files){
		
		//console.log(files);
		
		Upload.PostaFile.element.next('.input_text').val(files.data[0].name);
		
		var progress = parseInt((files.size_completed/files.size)*100);
		
		Upload.PostaFile.element.next('.input_text').val('Enregistrement en cours ('+progress+'%)');
		
		if(progress > 100){
			progress = 100;		
		}
		
		if(progress >= 100){
			
			Upload.PostaFile.element.next('.input_text').val('Enregistrement en cours ('+progress+'%)');

			if(files.data[0].php_response)
			{
							
				var json = jQuery.parseJSON(files.data[0].php_response);
				
				Upload.PostaFile.element.next('.input_text').val('Enregistrement terminé ('+progress+'%)');

				var title = Upload.PostaFile.element.parent().parent().parent().parent().parent().parent().find("input[name='media_title']");

				$.post('/Default/media/update/', {idmedia: json.idmedia,title:title.val()}, function(data){
					
					var data = jQuery.parseJSON(data);
					
						$('.loading_ajax').remove();

						$(this).oneTime('3s',function(){
							$('.file-name').attr('value','');
						});
					if(data != 0){
						
						if(data.hero == 1){var checked='checked';}else{var checked=null;}
						
						var html =	'<div class="item" style="clear:both;"><div class="media_title">'+ data.title +'</div><div class="media_time"><div class="checker" id="uniform-type"><span class="'+ checked +'"><input type="checkbox" id="type" value="'+ data.idmedia +'" name="media_hero" data="{type:\''+ data.type +'\',idmedia:'+ data.idmedia +'}" style="opacity:0;filter:alpha(opacity=0);-moz-opacity:0;"></span></div></div><div class=media_delete media_delete" id="deletemedia_'+ data.idmedia +'"></div><div class="clear"></div></div>';	
					
						Upload.PostaFile.element.parent().parent().parent().parent().parent().parent().parent().children('.media_list').fadeIn(function(){
							  $(this).append(html);  
							  $(".loading_ajax").remove();
						
						});

						Upload.PostaFile.stopUpload(Upload.PostaFile.mvelement);
					}
					
				});

			}
			
		}
	}
}



Core.Forms = {
	Initialize : function() {
		
		Core.Forms.Commons();
		Core.Forms.Hint();
		
	},
	Uniform: function(){
		$(".form input[type=radio],.form input[type=checkbox], textarea, select, button").uniform();
	},
	UniformUpdate: function(){
		
		//$(".form input[type=radio],.form input[type=checkbox], textarea, select, button").uniform();
		
		//$.uniform.update("select");
		$.uniform.update(".form input[type=radio],.form input[type=checkbox], textarea, select, button");
	},
	EmailExist : function(element_id, error_id){
		
		var email = $(element_id).val();
		
		if(email != ''){
			
			$.ajax({
				  type: 'POST',
				  url: '/Default/auth/email-exist',
				  data: {email: email},
				  async : false,
				  success: function(data, textStatus, xhr) {
					  if(data == 'false'){
							$(error_id).slideDown(function(){
								$(error_id + ' span').css('display','none');
								// $(error_id + '
								// span.required').css('display','inline');
								$(error_id + ' span.exist').css('display','inline');
							});
							
							$(element_id).parent().removeClass('valid').addClass('error');
							
							Core.Auth.ValidEmail = false;
							return false;
						}else{
							$(element_id).parent().removeClass('error').addClass('valid');
							$(error_id).slideUp(function(){
								$(error_id + ' span.exist').css('display','none');
							});
							Core.Auth.ValidEmail = true;
							return true;
						}
				  }
			});

		}
		
		
	},
	PseudoExist : function(element_id,element_type_id,error_id){
		
		var pseudo = $(element_id).val();
		var type = $(element_type_id).val();
		
		if(pseudo != ''){
		
			$.ajax({
				  type: 'POST',
				  url: '/Default/auth/pseudo-exist',
				  data: {pseudo:pseudo,type:type},
				  async : false,
				  success: function(data, textStatus, xhr) {
						
						if(data == 'false'){
							$(error_id).slideDown(function(){
								$(error_id + ' span').css('display','none');
								// $(error_id + '
								// span.required').css('display','inline');
								$(error_id + ' span.exist').css('display','inline');
							});
							
							$(element_id).parent().removeClass('valid').addClass('error');
							
							Core.Auth.ValidPseudo = false;
							
							return false;
						}else{
							$(element_id).parent().removeClass('error').addClass('valid');
							$(error_id).slideUp(function(){
								$(error_id + ' span.exist').css('display','none');
							});
							
							Core.Auth.ValidPseudo = true;
							//console.log(Core.Auth.ValidPseudo);
					
							return true;
						}
						
					}
			});
			
		
		}
		
		
	},
	Commons : function(){
		
			$.metadata.setType("attr", "data");

			$(".select-input").die().live('click',function(){
				$('.marker-container').css('display','none');
				$(this).parent().find('.marker-container').toggle();				
				return false;
			});
			
			$(".marker-container").die().mouseleave(function(){
				$('.marker-container').css('display','none');
				return false;
			});
			
			$(".select-list a").die().live('click', function(e){
				e.preventDefault();
				$(this).parent().parent().parent().find('input[type=hidden]').attr('value',$(this).metadata().item_value);
				$(this).parent().parent().parent().find('input[type=text]').attr('value',$(this).metadata().item_value);
				$(this).parent().parent().parent().find('span[class=name]').html($(this).metadata().item_name);
				$('.marker-container').css('display','none');
			});
			
			$('.select-list').die().live('mouseleave',function(){
				
				$('.marker-container').css('display','none');
				
			});
			
			/* SEARCH */

			$('#search').die().live('submit',function(e){
				e.preventDefault(); 
				$(this).ajaxSubmit( {
			          success : function(datas) {
			            if(datas != 0){
			            	$("#content").html(datas);
			            }
			          }
				});
				
			});
			
			/* BIND FILTER */
			$('.filter .select-list a.refresh, .filter input.refresh').die().live('click',function(){
				$('.filter').ajaxSubmit({
				beforeSend : function() { 
					$('body').prepend('<div class="loading_ajax" style="z-index:100;width:100%;height:100%;position:absolute;background-color:white;opacity:0.8;"><img src="/img/front/ajax-loader.gif" style="position:absolute;left:50%;margin-left-33px;top:50%;"/></div>');
					
	    			$(".loading_ajax").css('height', $(document).height());
					$(".loading_ajax").css({'opacity': 0.5})
				},
				 success : function(datas) {
		            if(datas != 0){
		            	$(".loading_ajax").remove();
		            	$("#content").html(datas);
		            	//$('html, body').animate({scrollTop:0}, 'fast');
		            }
		          }		
				});
			});
		
	},
	NotEmpty : function(element_id, error_id){
		if($(element_id).val() == '' || $(element_id).val() == undefined){
			$(error_id).slideDown(function(){
				$(error_id + ' span').css('display','none');
				$(error_id + ' span.required').css('display','inline');
			});
			
			$(element_id).parent().removeClass('valid').addClass('error');
			
			Core.Auth.ValidRegisterForm = false;
			return false;
		}else{
			$(element_id).parent().removeClass('error').addClass('valid');
			$(error_id).slideUp(function(){
				$(error_id + ' span.required').css('display','none');
			});
			Core.Auth.ValidRegisterForm = true;
			return $(element_id).val();
		}
	},
	isUrl : function(element_id, error_id){

		var urlRegxp = /[-a-zA-Z0-9@:%_\+.~#?&//=]{2,256}\.[a-z]{2,4}\b(\/[-a-zA-Z0-9@:%_\+.~#?&//=]*)?/gi;
		
		
		if(urlRegxp.test($(element_id).val())) {
			$(element_id).parent().removeClass('error').addClass('valid');
			$(error_id).slideUp(function(){
				$(error_id + ' span.required').css('display','none');
			});
			Core.Auth.ValidRegisterForm = true;
			return $(element_id).val();
		}else{

			$(error_id).slideDown(function(){
				$(error_id + ' span').css('display','none');
				$(error_id + ' span.required').css('display','inline');
			});
			$(element_id).parent().removeClass('valid').addClass('error');
			
			Core.Auth.ValidRegisterForm = false;
			return false;

		}
	},
	isCheck : function(element_id, error_id){
		if($(element_id).is(':checked')){
			$(element_id).parent().removeClass('error').addClass('valid');
			$(error_id).slideUp(function(){
				$(error_id + ' span.required').css('display','none');
			});
			Core.Auth.ValidRegisterForm = true;
			return $(element_id).val();
		}else{

			$(error_id).slideDown(function(){
				$(error_id + ' span').css('display','none');
				$(error_id + ' span.required').css('display','inline');
			});
			
			$(element_id).parent().removeClass('valid').addClass('error');
			
			Core.Auth.ValidRegisterForm = false;
			return false;

		}
	},
	Blur:function(element_id, callback){
		$(element_id).blur(function(){
			
			 var result = eval(callback);
			Core.Auth.ValidRegisterForm = true;
			return result;
		});
	},
	EqualTo:function(element_id,element_compare, error_id){
		
		if ($(element_id).val() != $(element_compare).val() && $(element_id).val() != '') {
				// console.log($(element_id).val() + $(element_compare).val())
				$(error_id).slideDown(function(){
					$(error_id + ' span').css('display','none');
					$(error_id + ' span.equalTo').css('display','inline');
				});
				Core.Auth.ValidRegisterForm = false;
				return false;
			
		}else{
			
			Core.Auth.ValidRegisterForm = true;
				return true;
		}
		
	},
	Hint: function(){
		

		$(".hint").live('focus',function() {
			if($(this).attr("value") == $(this).attr("alt")) {
				$(this).attr("value", "");
			}
		});

		$(".hint").live('blur',function() {
			if($(this).attr("value") == "") {
				$(this).attr("value", $(this).attr("alt"));
			}	
		});
		
	},
	isEmail : function(element_id, error_id){
		validRegExp = /^[^@]+@[^@]+.[a-z]{2,}$/i;
		if ($(element_id).val().search(validRegExp) == -1){
			$(error_id).slideDown(function(){
				$(error_id + ' span').css('display','none');
				$(error_id + ' span.required').css('display','inline');
			});
			
			$(element_id).parent().removeClass('valid').addClass('error');
			
			Core.Auth.ValidRegisterForm = false;
			return false;
		}else{
			$(element_id).parent().removeClass('error').addClass('valid');
			$(error_id).slideUp(function(){
				$(error_id + ' span.required').css('display','none');
			});
			Core.Auth.ValidRegisterForm = true;
			return $(element_id).val();
		}
	},
	EmailValid: function(strEmail){

		validRegExp = /^[^@]+@[^@]+.[a-z]{2,}$/i;
		   // search email text for regular exp matches
		    if (strEmail.search(validRegExp) == -1) 
		   {
		      return false;
		    } 
		    return true; 
	

	}
}

Core.Home = {
	Initialize : function() {
	
	},
	myindex : 0,
	SoundplaceDisplay : function(strUrl){
			$('#home-map').append('<div class="loader-ajax-medium loader-ajax" ></div>');
			$("#home-map").load(strUrl,{ size: "small"},function(data){
				smallmap = Core.Map;
				smallmap.Initialize();
				Core.Map.showmap = true;
			});
			return false;
	},
	HeaderCarousel : function(){

			function header_carousel_initCallback(carousel) {

				Core.Common.headerCarousel = carousel;

			    jQuery('#header-carousel-next').bind('click', function() {
			        carousel.next();
			        return false;
			    });

			    jQuery('#header-carousel-prev').bind('click', function() {
			        carousel.prev();
			        return false;
			    });
			};

		   // Ride the carousel...
		   $("#header-carousel").jcarousel({
		        scroll: 1,
				visible:1,
				wrap: 'both',
				animation: 1000,
		        initCallback: header_carousel_initCallback,
		        // This tells jCarousel NOT to autobuild prev/next buttons
		        buttonNextHTML: null,
		        buttonPrevHTML: null
		    });
	},
	prevNextTrigger: false,
	Carousel : function(){
			/* posts carousel */
			function mycarousel_initCallback(carousel) {
			   
				
				jQuery('#carousel-post-page a').bind('click', function() {
					Core.Home.prevNextTrigger = true;
					$("#carousel-post-page a").removeClass('active');
					
					$(this).addClass('active');
					linkposition = parseInt($('#carousel-post-page a').index(this)) + 1;
					
					$('#carousel-category div').removeClass('active');
					$( $('#carousel-category div').get(linkposition-1)).addClass('active');
			
					
			        carousel.scroll(jQuery.jcarousel.intval( linkposition ));
			        return false;
			    });

			    jQuery('.carousel-post-next').bind('click', function() {
					Core.Home.prevNextTrigger = true;
					// Get number of elements
					total = parseInt( $("#carousel-post-page a").size() );

					// Get current position
					var index = $('#carousel-post-page a.active').index();
					index = parseInt(index) + 1;
					
					if(index == total){
						index = 0;
					}
					

					$('#carousel-category div').removeClass('active');
					$( $('#carousel-category div').get(index)).addClass('active');

					if (index < total) {

						$('#carousel-post-page a').removeClass('active');
						$( $('#carousel-post-page a').get(index)).addClass('active');
						
						

					};
		        	carousel.next();
			        return false;
			    });

			    jQuery('.carousel-post-prev').bind('click', function() {
				
					Core.Home.prevNextTrigger = true;
				
					// Get number of elements
					total = parseInt( $("#carousel-post-page a").size() );

					// Get current position
					var index = $('#carousel-post-page a.active').index();
					index = parseInt(index) - 1;
	
					if(index == -1){
						index = total-1;
					}
					
					$('#carousel-category div').removeClass('active');
					$( $('#carousel-category div').get(index)).addClass('active');

					if (index < total && index >=0) {
						$('#carousel-post-page a').removeClass('active');
						$( $('#carousel-post-page a').get(index)).addClass('active');

					};
		        	carousel.prev();
			        return false;
			    });
			};

			$("#body .post-home").jcarousel({
			    scroll: 1,
			    auto:10,
			    wrap:'circular',
			    initCallback: mycarousel_initCallback,
			    itemVisibleInCallback :  {
			    	  onAfterAnimation: function(a,b,index,d){
						if(Core.Home.prevNextTrigger == false)
						{
                        	
							if(Core.Home.myindex > (a.options.size - 1)){
								Core.Home.myindex = 0;
							}
								
							$('#carousel-category div').removeClass('active');
							$( $('#carousel-category div').get(Core.Home.myindex)).addClass('active');
							
							$('#carousel-post-page a').removeClass('active');
							$( $('#carousel-post-page a').get(Core.Home.myindex)).addClass('active');
							
							Core.Home.myindex = Core.Home.myindex + 1;
						}else
							Core.Home.prevNextTrigger = false;
						
					}
			    },
			    buttonNextHTML: null,
			    buttonPrevHTML: null
			});
		
		
	}
	
}

Core.Artist = {
	Initialize : function() {
		Core.Artist.Edit();
		Core.Artist.EditOption();
		
		Core.Artist.Bookmark();
		
		Core.Artist.artist_proposal();
		
		Core.Artist.SearchFnac();
		Core.Artist.DeleteFnac();
		Core.Artist.DeleteJoinArtist();
		
		Core.Artist.Talent();

	},
	Talent : function(){
		
		
		$('#talent-content a, .pagination_container a').die().live('click',function(){
			
			var iframe = $('#iframe').length;
			if (iframe > 0 && !$(this).hasClass('login-light-participer') && !$(this).hasClass('voter')) {
				
				var self = $(this);
				
				var attr = self.attr('href');
				var target = self.attr('target');

				// For some browsers, `attr` is undefined; for others,
				// `attr` is false.  Check for both.
				if ((typeof attr !== 'undefined' && attr !== false) &&(typeof target !== 'undefined' && target !== false )) {
					if(self.hasClass('preview') || self.hasClass('next') || self.hasClass('page_number') || self.hasClass('cms'))
					var href = self.attr('href')+'&iframe=true';
					else
					var href = self.attr('href')+'?iframe=true';
					window.location = href;
				}

				
			}
			
		});
		
		$('.login-light-participer').die().live('click', function(e){
			if ($(this).hasClass('lightbox')) {
				e.preventDefault();
				var url = $(this).attr('href');
				$.post(url, {data: true}, function(data, textStatus, xhr) {
			
				  	if (data) {

						var iframe = $('#iframe').length;
						if (iframe > 0) {

						    var strurl = '/Default/Artist/talent-lightbox?iframe=true';
							var talenturl = "/jeunes-talents/participer?iframe=true";

						}else{

							var talenturl = "/jeunes-talents/participer";
						    var strurl = '/Default/Artist/talent-lightbox';							
						}
						//console.log(data);
						if (data == 'redir') {

							window.location = talenturl;
						}else{

							Lightbox.open(strurl,'Core.Auth.Login()');
						
						}
						
					};
				});
				
			}else{

				var iframe = $('#iframe').length;
				if (iframe > 0) {

				    var strurl = '/Default/Artist/talent-lightbox?iframe=true';
					var talenturl = "/jeunes-talents/participer?iframe=true";

				}else{

					
					var talenturl = "/jeunes-talents/participer";
				    var strurl = '/Default/Artist/talent-lightbox';							
				}

					window.location = talenturl;
			}

		})
	
		
	},
	DeleteJoinArtist: function(){
		$('.artist_join_delete').die().live('click',function(e){
			
			e.preventDefault();

			$(this).parent().remove();

		});
	},
	DatePicker: function(){
		
		$('.select-input-date').die().live('click',function(){
			
			$(".edit-concert-form input[name='date']").focus();
			
		});
		
		$(".edit-concert-form input[name='date']").datepicker({
			minDate: 0,
			onSelect: function(dateText, inst) { 
				$('.ui-state-default').addClass('notaddress');	
			},
			dateFormat: 'dd.mm.yy'
		});
	},
	Autocomplete : function(){
		
		
		/* ADD ARTIST HERO*/
		$(".edit-concert-form input[name='artist_hero']").die().live('click',function(e){	
			
			e.preventDefault();

				var dom = $(this);

				if(dom.parent('span').hasClass('checked')){
					dom.parent('span').removeClass('checked');
					dom.attr('checked', false);
				}else{
					dom.parent().parent().parent().parent().parent().find("input[name='artist_hero']").parent('span').removeClass('checked');
					dom.parent('span').addClass('checked');
					dom.attr('checked', true);
				}

		});
		
		$(".edit-concert-form input[name='artist']").autocomplete({
			
    		source: function(request, response) {			
                        $.ajax({
                            url: "/Default/artist/autocomplete",
                            dataType: "json",
                            data: {
                                maxRows: 12,
                                name_startsWith: request.term
                            },
                            complete: function(data) {
                            	//console.log(data.responseText);
                            	var json = jQuery.parseJSON(data.responseText);
                                response($.map(json, function(item) {
                                	return {
                                        value: item.fullname,
                                        label: item.fullname,
                                        id : item.idartist
                                    };
                                }));
                            }
                        });
                    },
                    minLength: 2,
					appendTo : ".autocomplete",
					select: function(event, ui) {
                    	
                		 var html =	'<div class="item" style="clear:both;"><input type="hidden" value="'+parseInt(ui.item.id)+'" name="idartist[]"/><div class="media_title">'+ ui.item.label +'</div><div class="media_time"><div class="checker" id="uniform-type"><span><input type="radio" value="'+parseInt(ui.item.id)+'" name="artist_hero" /></span></div></div><div class="media_delete media_delete artist_join_delete" id="deletemedia_'+ parseInt(ui.item.id) +'"></div><div class="clear"></div></div>';	
 						
                		 $('.artist_list').fadeIn(function(){
                			 $('.artist_list').append(html);
                		 });

                		 $('#idartist-invalid').hide();
                	},
                	close: function(){
                		$(this).val('');
                	},
                	open: function() {
                		$('.autocomplete a').addClass("notaddress");
                	}
        });
	
	},
	AutocompleteFnac : function(){
		$("#search-artist-form input[name='terms']").autocomplete({
    		source: function(request, response) {			
                        $.ajax({
                            url: "/Default/artist/autocomplete-fnac",
                            dataType: "json",
                            data: {
                                maxRows: 12,
                                name_startsWith: request.term
                            },
                            complete: function(data) {
                            	//console.log(data.responseText);
                            	var json = jQuery.parseJSON(data.responseText);
                                response($.map(json, function(item) {
                                	return {
                                        value: item.nomart + ' ' +item.pnmart,
                                        label: item.nomart + ' ' +item.pnmart,
                                        id : item.idfnac_artiste
                                    };
                                }));
                            }
                        });
                    },
                    minLength: 3,
					appendTo : ".autocomplete",
					select: function(event, ui) {
                		$("#search-artist-form input[name='idfnac_artiste']").val(ui.item.id);
                	},
                	open: function() {
                		$('.autocomplete a').addClass("notaddress");
                	}
        });
	},
	DeleteFnac : function(){
		$('#search-artist-form .title .date_delete').die().live('click',function(e){
			e.preventDefault();
			
			var dom = $(this);
			var url = dom.attr('href');

			$.ajax({
				  type: 'POST',
				  url: url,
				  success: function(idmedia){
					if(idmedia == 1){
						dom.parent().parent().html('');
					}				
				}
			});
			
		});
	},
	SearchFnac: function(){
		$('#search-artist-form .submit-button:first').die().live('click',function(e){
			
			e.preventDefault();
			
			var terms = Core.Forms.NotEmpty("#search-artist-form #terms", "#terms-invalid");
	
				if (terms) {
					$('#search-artist-form').ajaxSubmit( {
						success : function(datas) {
				            if(datas != 0){
				            	$(".date_list:first").html(datas);
				            }
				         }
				    });
				}			
		});
	
	},
	setNumberBookmark : function(){
		var nb = parseInt($('.heart_container .number').html());
		$('.heart_container .number').html((nb+1));
		$('.heart_container .number').css({'visibility':'visible'});
	},
	Bookmark: function(){
		$('.bookmark_artist, .favorite').live('click', function(e){
			e.preventDefault();
			var url = $(this).attr('href');
			Lightbox.open(url,'Core.Auth.Login();');
			
		});
	},	
	EditOption : function(){
		
		/* ADD FILES MUSIC*/
		$('#edit-artist-form .add-file, #register-artist-form .add-file').die().live('click',function(e){
			
			e.preventDefault(); 

			if($(this).parent().find("input[name='media_optin']").is(':checked')){
				$(this).parent().find('.upload-invalid').hide('fast',function(){
					Upload.PostaFile.startUpload('multiUploadmusic_file');
				});
			}else{
				$(this).parent().find('.upload-invalid').show();
			}

		});

		/* ADD FILES HERO*/
		$("#edit-artist-form input[name='media_hero'], #register-artist-form input[name='media_hero']").die().live('click',function(e){	
			
			e.preventDefault();
			
			var dom = $(this);
			var data = $(this).metadata();

			$.post('/Default/media/update/', {idmedia: data.idmedia,type:data.type,hero:1}, function(data){
			
				var data = jQuery.parseJSON(data);

				if(data.hero == 0){
					dom.parent().parent().parent().parent().parent().find("input[name='media_hero']").parent('span').removeClass('checked');
				}else if(data.hero == 1){
					dom.parent().parent().parent().parent().parent().find("input[name='media_hero']").parent('span').removeClass('checked');
					dom.parent('span').addClass('checked');
				}
				
			});

		});
		
		/* ADD FILES PHOTO*/
		$('#edit-artist-form .add-file-photo, #register-artist-form .add-file-photo').die().live('click',function(e){
			
			e.preventDefault(); 

		});
		
		/* ADD VIDEO */
		$('#edit-artist-form .add-video, #register-artist-form .add-video').die().live('click',function(e){
			
			e.preventDefault(); 

			var video_title = Core.Forms.NotEmpty("input[name=video_title]", "#video-invalid");
			var video_type = Core.Forms.isCheck("input[name=video_type]", "#video-invalid");
			var video = Core.Forms.isUrl("input[name=video]", "#video-invalid");
			
			var url = '/Default/artist/add-video';
			
			if(video && video_title && video_type){
			
			$.ajax({
				  type: 'POST',
				  url: url,
				  data: 'video='+video+'&video_title='+video_title+'&video_type='+video_type,
				  success: function(idmedia){
					if(idmedia != 0){
					
					   var html =	'<div class="item" style="clear:both;"><div class="media_title">'+ video_title +'</div><div class="media_time"></div><div class="media_delete media_delete" id="deletemedia_'+ parseInt(idmedia) +'"></div><div class="clear"></div></div>';	
						
					   $('.video_list').fadeIn(function(){
						   $('.video_list').append(html);  
					   });
					
					}
				
				  }
			});
			}
			
		});

		/* ADD LINK */
		$('#edit-artist-form .add-link, #register-artist-form .add-link').die().live('click',function(e){
			
			e.preventDefault(); 
			$('#link-invalid').css('display','none');
			$('#linktitle-invalid').css('display','none');
			
			var linkValue = $('input[name=link]').val();
			var linkTitleValue = $('input[name=link_title]').val();
			
			var url = '/Default/artist/add-link';
			
			var link =  $('input[name=link]').val();
			var linkAlt =  $('input[name=link]').attr('alt');
			
			if (linkAlt != link && link != '') {
				var isurl = true;
			}else{
				var isurl = false;
				$('#link-invalid').slideDown();
			}
			
			var linktitle =  $('input[name=link_title]').val();
			var linktitleAlt =  $('input[name=link_title]').attr('alt');
			
			if (linktitle != linktitleAlt && linktitleAlt != '') {
				var link_title = true;
			}else{
				var link_title = false;
				$('#linktitle-invalid').slideDown();
			}

			if(isurl && link_title){
				
				$.ajaxSetup({
				   jsonp: null,
				   jsonpCallback: null
				});
				
				
				
				$.post( url, {link: linkValue , link_title : linkTitleValue}, function(result) {
				  		if(result.idmedia != 0){

						   var html = '<div class="item" style="clear:both; "><div class="media_title media media-title-link"><a href="'+result.url+'" class="notaddress" target="_blank">'+ result.title_link +'</a></div><div class="media_delete media_delete" id="deletemedia_'+ parseInt(result.idmedia) +'"></div><div class="clear"></div></div>';	

						   $('.link_list').fadeIn(function(){
							   $('.link_list').append(html); 
							   $('input[name=link]').val(  $('input[name=link]').attr('alt') );
							   $('input[name=link_title]').val(  $('input[name=link_title]').attr('alt') );
						   });


						}
				}, 'json');
		
			}
			
			
			return false;
		});
		
		$('#edit-artist-form input[name=itune], #register-artist-form input[name=itune]').die().live('click',function(e){	
			
			if($(this).val() == 1 ){
				$('.link_music').show();
			}else{
				$('.link_music').hide();
			}
		});
		
		/* ADD MUSIC LINK */
		$('#edit-artist-form .add-music-link, #register-artist-form .add-music-link').die().live('click',function(e){



			e.preventDefault(); 
			$('#link-music-invalid').css('display','none');
			$('#linktitle-music-invalid').css('display','none');
			
			var linkValue = $('input[name=link_music]').val();
			var linkTitleValue = $('input[name=link_title_music]').val();
			
			var url = '/Default/artist/add-link';
			
			var link =  $('input[name=link_music]').val();
			var linkAlt =  $('input[name=link_music]').attr('alt');
			
			if (linkAlt != link && link != '') {
				var isurl = true;
			}else{
				var isurl = false;
				$('#link-music-invalid').slideDown();
			}
			
			var linktitle =  $('input[name=link_title_music]').val();
			var linktitleAlt =  $('input[name=link_title_music]').attr('alt');
			
			if (linktitle != linktitleAlt && linktitleAlt != '') {
				var link_title = true;
			}else{
				var link_title = false;
				$('#linktitle-music-invalid').slideDown();
			}

			if(isurl && link_title){
				
				$.ajaxSetup({
				   jsonp: null,
				   jsonpCallback: null
				});
							
				$.post( url, {link: linkValue , link_title : linkTitleValue, link_type : 'link_music'}, function(result) {
				  		if(result.idmedia != 0){

						   var html = '<div class="item" style="clear:both; "><div class="media_title media-title-link"><a href="'+result.url+'" class="notaddress" target="_blank">'+ result.title_link +'</a></div><div class="media_delete media_delete" id="deletemedia_'+ parseInt(result.idmedia) +'"></div><div class="clear"></div></div>';	

						   $('.link_list_music').fadeIn(function(){
							   $('.link_list_music').append(html); 
							   $('input[name=link_music]').val(  $('input[name=link_music]').attr('alt') );
							   $('input[name=link_title_music]').val(  $('input[name=link_title_music]').attr('alt') );
						   });


						}
				}, 'json');
		
			}
			
			
			return false;



		
		});

		// delete media
		$('#edit-artist-form .media_delete,  #register-artist-form .media_delete').die().live('click',function(e){
			
			e.preventDefault(); 
			
			var dom = $(this);
			url = '/Default/artist/delete-media';
			var id = dom.attr('id');
			var tab = id.split('_');
			id = tab[1];
			
			//console.log(dom.parent());
			
			$.post(url, {id: id}, function(data){
					dom.parent().remove();
					
					
					
					
			});
		})
		
	},
	Edit : function(){
		
		//Navigation 
		$('.edit-buttons a').die().live('click',function(e){
			
			e.preventDefault();
			
			var id = "#"+$(this).attr('alt');	

			$('.edit-buttons a').removeClass('selected');
			$(this).addClass('selected');
			
			//$('.tab').hide();
			$('.tab:not('+id+')').hide('fast',function(){
				$(id).show('fast',function(){
					$('html, body').animate({scrollTop:$("#content").position().top?($("#content").position().top-63):0}, 'fast');
				});
			});

			
		});
		
		$('a.endstep').die().live('click',function(e){
			
			e.preventDefault();
			
			var id = "#"+$(this).attr('alt');	

			$('.edit-buttons a').removeClass('selected');
			$(this).addClass('selected');
			
			//$('.tab').hide();
			$('.tab:not('+id+')').hide('fast',function(){
				$(id).show('fast',function(){
					$('html, body').animate({scrollTop:$("#content").position().top?($("#content").position().top-63):0}, 'fast');
				});
			});

			Lightbox.open('/Default/artist/talent-edit');
			
		});
		
		// On submit
		$('#edit-artist-form').die().live('submit',function(e){
			
			e.preventDefault();
			
			var mode = $('#edit-artist-form input[name=register]').val();
			var listItem = $('.edit-buttons a.selected');
			var currentStep = $('.edit-buttons a').index(listItem);
			
			var pseudo = Core.Forms.NotEmpty("#edit-artist-form #pseudo", "#pseudo-invalid");
			var fullname = Core.Forms.NotEmpty("#edit-artist-form #fullname", "#fullname-invalid");
			var login = Core.Forms.NotEmpty("#edit-artist-form #login", "#login-invalid");
			var login_exist = Core.Forms.EmailExist("#edit-artist-form #login", "#login-invalid");
			var pseudo_exist = Core.Forms.PseudoExist("#edit-artist-form #pseudo","input[name=type]" ,"#pseudo-invalid");
			var password_value = $("#password").attr('value');
			var confirm_password_value = $("#confirm_password").attr('value');
			  
			if(password_value != '' || confirm_password_value != ''){
				
			   var password = Core.Forms.NotEmpty("#edit-artist-form #password", "#password-invalid");
			   var confirm_password = Core.Forms.NotEmpty("#confirm_password", "#confirm_password-invalid");
			   
				if (confirm_password) {
					var confirm_passwordEqual = Core.Forms.EqualTo("#confirm_password", "#edit-artist-form #password", "#confirm_password-invalid");
				}

				if (pseudo && login && Core.Auth.ValidPseudo && Core.Auth.ValidEmail && password && confirm_password && confirm_passwordEqual && fullname) {
						$(this).ajaxSubmit( {
				          success : function(datas) {
				            if(datas != 0){
				            	//Chargement du contenu
				            	$("#content").html(datas);
				            	
				            	//etape suivante
				            	if(mode == 1){
				            		$($('.edit-buttons a').get((currentStep + 1))).click();
				            	}
				            }
				          }
				    });
				}			
				
			}else{
				if (pseudo && Core.Auth.ValidPseudo && Core.Auth.ValidEmail && login) {
						$(this).ajaxSubmit( {
				          success : function(datas) {
				            if(datas != 0){
				            	$("#content").html(datas);
				            	
				            	//etape suivante
				            	if(mode == 1){
				            		$($('.edit-buttons a').get((currentStep + 1))).click();
				            	}
				            }
				          }
				    });
				}
			}
			
		});
	},
	artist_proposal: function(){
		
		Core.Forms.Blur("#proposal-artist-form #artist_name", 'Core.Forms.NotEmpty("#artist_name", "#artist_name-invalid")');
		Core.Forms.Blur("#proposal-artist-form #artist_email", 'Core.Forms.NotEmpty("#artist_email", "#artist_email-invalid")');
		Core.Forms.Blur("#proposal-artist-form #group_name", 'Core.Forms.NotEmpty("#group_name", "#group_name-invalid")');
		Core.Forms.Blur("#proposal-artist-form #idplace_region", 'Core.Forms.NotEmpty("#idplace_region", "#idplace_region-invalid")');
		Core.Forms.Blur("#proposal-artist-form #idartist_category", 'Core.Forms.NotEmpty("#idartist_category", "#idartist_category-invalid")');
		
		// on submit
		$('#proposal-artist-form').die().live('submit',function(e){
			
			e.preventDefault(); 
			
			var artist_name = Core.Forms.NotEmpty("#proposal-artist-form #artist_name", "#artist_name-invalid");
			var artist_email = Core.Forms.NotEmpty("#proposal-artist-form #artist_email", "#artist_email-invalid");
			var group_name = Core.Forms.NotEmpty("#proposal-artist-form #group_name", "#group_name-invalid");
			var idplace_region = Core.Forms.NotEmpty("#proposal-artist-form #idplace_region", "#idplace_region-invalid");
			var idartist_category = Core.Forms.NotEmpty("#proposal-artist-form #idartist_category", "#idartist_category-invalid");
				
			if (artist_name && artist_email && group_name && idplace_region && idartist_category) {

					$(this).ajaxSubmit( {
			          success : function(datas) {
			            if(datas != 0){
			            	$("#content").html(datas);
			            }
			          }
			    });
			}
				
				
		})
	}
}

Core.Blog = {
	Initialize : function() {
	Core.Blog.Article();
	//Core.Review.AddReview();
		
		/*
		 * $('.footer_elem').click(function(){
		 * $('.footer_elem').removeClass('selected');
		 * $(this).addClass('selected');
		 * 
		 * var id = $(this).attr('id'); var tab = id.split('_');
		 * 
		 * var elem = tab[1]; $('.footer_container').hide();
		 * $('#actu_'+elem).show(); });
		 */
	},
	Article : function() {
		$('#actuality_page .pagination_container_principal .pagination a').die().live('click',function(e){
			e.preventDefault(); 
			var dom = $(this);
			var url = dom.attr('href');
			$.ajax( {
				type : "GET",
				url : url,
				success : function(data) {
					if(data != 0){
						$('#content').html(data);
					}
				}
			});
		});	
	}
}

Core.Concert = {
	Initialize : function() {
		Core.Concert.Edit();
		Core.Concert.DeleteArtistDate();
		Core.Concert.EditArtistDate();
	},
	EditArtistDate : function(){
		$('.edit-concert-form .date_edit').die().live('click',function(e){
			
			e.preventDefault(); 

			var dom = $(this);
			var id = dom.attr('id');
			var tab = id.split('_');
			id = tab[2];
			
			url = '/Default/concert/edit?idconcert='+id;
			
			Lightbox.open(url);
			
		})
	},
	DeleteArtistDate : function(){
		$('.edit-concert-form .date_delete').die().live('click',function(e){
			
			e.preventDefault(); 
			
			var dom = $(this);
			url = '/Default/concert/delete-artist-date';
			var id = dom.attr('id');
			var tab = id.split('_');
			id = tab[2];
			
			//console.log(dom.parent());
			
			$.post(url, {id: id}, function(data){
					dom.parent().html('');
			});
		})
	},
	Edit : function(){

		// On submit
		
		$('.edit-concert-form .add-date').die().live('click',function(e){
			
			number = $('.dateConcertElement').length;
	//		console.log(number);
			
			
			$('#date-invalid').css('display','none');
			e.preventDefault();
			
			var date 		= $(".edit-concert-form input[name='date']").val(); 
			var date_time 	= $(".edit-concert-form input[name='date_time']").val(); 
			var date_minute = $(".edit-concert-form input[name='date_minute']").val(); 
			
			if(date != '' && date_time != '' &&  date_minute != ''){
			
				var html = '<div style="clear: both;" class="item dateConcertElement"><input type="hidden" name="date[]" value="'+date+'"><input type="hidden" name="date_time[]" value="'+date_time+'"><input type="hidden" name="date_minute[]" value="'+date_minute+'"><div class="media_title">Le '+ date + ' à ' + date_time  +':'+ date_minute +'</div><div class="media_time"></div><div id="deletemedia_1" class="media_delete media_delete artist_join_delete"></div><div class="clear"></div></div>';

				$('.date_concert_list').fadeIn(function(){
					$(this).append(html);
				});
			
				$(".edit-concert-form input[name='date']").val(''); 
				$(".edit-concert-form input[name='date_time']").val(''); 
				$(".edit-concert-form input[name='date_minute']").val(''); 
				
				$('#date-invalid').css('display','none');
				
			}else{
			
				$('#date-invalid').css('display','inline');
			}
			
		});
		
		$('.edit-concert-form .submit-button').die().live('click',function(e){
			
			e.preventDefault(); 
			
			var concert = Core.Forms.NotEmpty(".edit-concert-form #concert", "#concert-invalid");
			var hall = Core.Forms.NotEmpty(".edit-concert-form #hall", "#hall-invalid");
			
			var idartist = Core.Forms.NotEmpty(".edit-concert-form input[name='idartist[]']", "#idartist-invalid");
			
			var date = Core.Forms.NotEmpty(".edit-concert-form input[name='date']", "#date-invalid");
			var date_time = Core.Forms.NotEmpty(".edit-concert-form input[name='date_time']", "#date-invalid");
			var date_minute = Core.Forms.NotEmpty(".edit-concert-form input[name='date_minute']", "#date-invalid");


			if (concert && hall && idartist && date && date_time && date_minute) {

						$('.edit-concert-form').ajaxSubmit( {
				          success : function(datas) {
				            if(datas != 0){
				            	
				            	$(".edit-concert-form .date_list").fadeIn(function(){
		                			 $(this).html(datas);
		                		 });

				            	$(".edit-concert-form input[type=text]").val('');
				            	$(".edit-concert-form textarea").val('');
				            	$(".edit-concert-form .media_list .item").remove();
				            	
				            	Lightbox.close();

				            }
				          }
				    });
			}			
		});
	

	},
	datePicker: function(){
	var dates_element =	$('.search_calendar').datepicker({
			altField: "#search_calendar_value",
			altFormat: "dd.mm.yy",
			minDate: 0,
			onSelect: function(dateText, inst) {
				
				$('.ui-state-default').addClass('notaddress');
				$('form.filter').ajaxSubmit({
					 success : function(datas) {
			            if(datas != 0){
			            	$("#content").html(datas);
			            }
			          }		
				});		
			},
			dateFormat: 'dd-mm-yy'
		});
	},
	Carousel: function(){

			function header_carousel_initCallback(carousel) {
			    jQuery('#header-carousel-next').bind('click', function() {
			        carousel.next();
			        return false;
			    });

			    jQuery('#header-carousel-prev').bind('click', function() {
			        carousel.prev();
			        return false;
			    });
			};

			// Ride the carousel...
		   $("#header-carousel").jcarousel({
		        scroll: 1,
				visible:1,
		        initCallback: header_carousel_initCallback,
		        // This tells jCarousel NOT to autobuild prev/next buttons
		        buttonNextHTML: null,
		        buttonPrevHTML: null
		    });

			/* posts carousel */
			function mycarousel_initCallback(carousel) {

			    jQuery('#carousel-post-page a').bind('click', function() {
					$("#carousel-post-page a").removeClass('active');
					$(this).addClass('active');
					linkposition = parseInt($('#carousel-post-page a').index(this)) + 1;
					
					$('#carousel-category div').removeClass('active');
					$( $('#carousel-category div').get(linkposition-1)).addClass('active');
			
					
			        carousel.scroll(jQuery.jcarousel.intval( linkposition ));
			        return false;
			    });

			    jQuery('.carousel-post-next').bind('click', function() {

					// Get number of elements
					total = parseInt( $("#carousel-post-page a").size() );

					// Get current position
					var index = $('#carousel-post-page a.active').index();
					index = parseInt(index) + 1;

					$('#carousel-category div').removeClass('active');
					$( $('#carousel-category div').get(index)).addClass('active');

					if (index < total) {

						$('#carousel-post-page a').removeClass('active');
						$( $('#carousel-post-page a').get(index)).addClass('active');
						
						

					};
		        	carousel.next();
			        return false;
			    });

			    jQuery('.carousel-post-prev').bind('click', function() {
					// Get number of elements
					total = parseInt( $("#carousel-post-page a").size() );

					// Get current position
					var index = $('#carousel-post-page a.active').index();
					index = parseInt(index) - 1;

					$('#carousel-category div').removeClass('active');
					$( $('#carousel-category div').get(index)).addClass('active');

					if (index < total && index >=0) {
						$('#carousel-post-page a').removeClass('active');
						$( $('#carousel-post-page a').get(index)).addClass('active');

					};
		        	carousel.prev();
			        return false;
			    });
			};

			$(".post-home").jcarousel({
			    scroll: 1,
			    initCallback: mycarousel_initCallback,
			    // This tells jCarousel NOT to autobuild prev/next buttons
			    buttonNextHTML: null,
			    buttonPrevHTML: null
			});
			
	}
}

Core.Hall = {
	Initialize : function() {
		Core.Hall.Edit();
		Core.Hall.EditOption();
		
		Core.Hall.DeleteFnac();
		Core.Hall.SearchFnac();
	},
	AutocompleteFnac : function(){
		
		$("#search-hall-form input[name='terms']").autocomplete({
    		source: function(request, response) {			
                        $.ajax({
                            url: "/Default/hall/autocomplete-fnac",
                            dataType: "json",
                            data: {
                                maxRows: 12,
                                name_startsWith: request.term
                            },
                            complete: function(data) {
                            	//console.log(data.responseText);
                            	var json = jQuery.parseJSON(data.responseText);
                                response($.map(json, function(item) {
                                	return {
                                        value: item.nomsal,
                                        label: item.nomsal,
                                        id : item.idfnac_salle
                                    };
                                }));
                            }
                        });
                    },
                    minLength: 3,
					appendTo : ".autocomplete",
					select: function(event, ui) {
                		$("#search-hall-form input[name='idfnac_hall']").val(ui.item.id);
                	},
                	open: function() {
                		$('.autocomplete a').addClass("notaddress");
                	}
        });
	},
	DeleteFnac : function(){
		$('#search-hall-form .title .date_delete').die().live('click',function(e){
			e.preventDefault();
			
			var dom = $(this);
			var url = dom.attr('href');

			$.ajax({
				  type: 'POST',
				  url: url,
				  success: function(idmedia){
					if(idmedia == 1){
						dom.parent().parent().hide();
					}				
				}
			});
			
		});
	},
	SearchFnac: function(){
		$('#search-hall-form .submit-button:first').die().live('click',function(e){
			
			e.preventDefault();
			
			var terms = Core.Forms.NotEmpty("#search-hall-form #terms", "#terms-invalid");
	
				if (terms) {
					$('#search-hall-form').ajaxSubmit( {
						success : function(datas) {
				            if(datas != 0){
				            	$(".date_list:first").html(datas);
				            }
				         }
				    });
				}			
		});
	
	},
	Autocomplete : function(){
	
		$(".edit-concert-form input[name='hall']").autocomplete({
    		source: function(request, response) {			
                        $.ajax({
                            url: "/Default/hall/autocomplete",
                            dataType: "json",
                            data: {
                                maxRows: 12,
                                name_startsWith: request.term
                            },
                            complete: function(data) {
                            	//console.log(data.responseText);
                            	var json = jQuery.parseJSON(data.responseText);
                                response($.map(json, function(item) {
                                	return {
                                        value: item.name,
                                        label: item.name + ' - ' +item.city,
                                        id : item.idhall,
                                        address : item.address
                                    };
                                }));
                            }
                        });
                    },
                    minLength: 3,
					appendTo : ".autocomplete",
					select: function(event, ui) {
                		$(".edit-concert-form  input[name='idhall']").val(ui.item.id);
                		$(".edit-concert-form  input[name='address']").val(ui.item.address);
                	},
                	open: function() {
                $('.autocomplete a').addClass("notaddress");
              }
        });

	
	},
	EditOption : function(){
		
		/* ADD FILES MUSIC*/
		$('#edit-hall-form .add-file,#register-hall-form .add-file,').die().live('click',function(e){
			
			e.preventDefault(); 

			if($(this).parent().find("input[name='media_optin']").is(':checked')){
				$(this).parent().find('.upload-invalid').hide(function(){
					Upload.PostaFile.startUpload('multiUpload');
				});
			}else{
				$(this).parent().find('.upload-invalid').show();
			}

		});
		

		/* ADD FILES HERO*/
		$("#edit-hall-form input[name='media_hero'], #register-hall-form input[name='media_hero']").die().live('click',function(e){	
			
			e.preventDefault();
			
			var dom = $(this);
			var data = $(this).metadata();

			$.post('/Default/media/update/', {idmedia: data.idmedia,type:data.type,hero:1}, function(data){
			
				var data = jQuery.parseJSON(data);

				if(data.hero == 0){
					dom.parent().parent().parent().parent().parent().find("input[name='media_hero']").parent('span').removeClass('checked');
				}else if(data.hero == 1){
					dom.parent().parent().parent().parent().parent().find("input[name='media_hero']").parent('span').removeClass('checked');
					dom.parent('span').addClass('checked');
				}
				
			});

		});
		
		/* ADD FILES PHOTO*/
		$('#edit-hall-form .add-file-photo, #register-hall-form .add-file-photo').die().live('click',function(e){
			
			e.preventDefault(); 

		});
		
		/* ADD VIDEO */
		$('#edit-hall-form .add-video, #register-hall-form .add-video').die().live('click',function(e){
			
			e.preventDefault(); 

			//var video = $('input[name=video]').val();
			//var video_title = $('input[name=video_title]').val();
			//var video_type = $('input[name=video_type]:checked').val();
			
			var url = '/Default/hall/add-video';
			

			var video_title = Core.Forms.NotEmpty("input[name=video_title]", "#video-invalid");
			var video_type = Core.Forms.isCheck("input[name=video_type]", "#video-invalid");
			var video = Core.Forms.isUrl("input[name=video]", "#video-invalid");
			
			if(video && video_title && video_type){
			
			$.ajax({
				  type: 'POST',
				  url: url,
				  data: 'video='+video+'&video_title='+video_title+'&video_type='+video_type,
				  success: function(idmedia){
					if(idmedia != 0){
					
					   var html =	'<div class="item" style="clear:both;"><div class="media_title">'+ video_title +'</div><div class="media_time"></div><div class="media_delete media_delete" id="deletemedia_'+ parseInt(idmedia) +'"></div><div class="clear"></div></div>';	
						
					   $('.video_list').fadeIn(function(){
						   $('.video_list').append(html);  
					   });
					
					}
				
				  }
			});
			
			}
			
		});
		
		
		
		/* ADD LINK */
		$('#edit-hall-form .add-link, #register-hall-form .add-link').die().live('click',function(e){
			
			e.preventDefault(); 

			var data = $('input[name=link]').val();
			var url = '/Default/hall/add-link';
			
			var isurl = Core.Forms.isUrl("input[name=link]", "#link-invalid");
			var link_title = Core.Forms.NotEmpty("input[name=link_title]", "#link-invalid");
			

			if(isurl && link_title){
			$.ajax({
				  type: 'POST',
				  url: url,
				  data: 'link='+data+'&link_title='+link_title,
				  success: function(idmedia){
					if(idmedia != 0){
					
					  var html = '<div class="item" style="clear:both;"><div class="media_title"><a href="'+data+'" class="notaddress" target="_blank">'+ link_title +'</a></div><div class="media_time"></div><div class="media_delete media_delete" id="deletemedia_'+ parseInt(idmedia) +'"></div><div class="clear"></div></div>';	
							
					   $('.link_list').fadeIn(function(){
						   $('.link_list').append(html);  
						   $('input[name=link]').val(' ');
						   $('input[name=link_title]').val('Titre du lien');
					   });
					
					}
				
				  }
			});
			}
			
		});
		
		
		// delete media
		$('#edit-hall-form .media_delete, #register-hall-form .media_delete').die().live('click',function(e){
			
			e.preventDefault(); 
			
			var dom = $(this);
			url = '/Default/hall/delete-media';
			var id = dom.attr('id');
			var tab = id.split('_');
			id = tab[1];
			
			//console.log(dom.parent());
			
			$.post(url, {id: id}, function(data){
					dom.parent().remove();
			});
		})
		
	},
	Edit : function(){

		// On submit
		$('#edit-hall-form').die().live('submit',function(e){
			
			e.preventDefault();
			
			var mode = $('#edit-hall-form input[name=register]').val();
			var listItem = $('.edit-buttons a.selected');
			var currentStep = $('.edit-buttons a').index(listItem);
			
			var pseudo = Core.Forms.NotEmpty("#edit-hall-form #pseudo", "#pseudo-invalid");
			var name = Core.Forms.NotEmpty("#edit-hall-form #name", "#name-invalid");
			var login = Core.Forms.NotEmpty("#edit-hall-form #login", "#login-invalid");
			var login_exist = Core.Forms.EmailExist("#edit-hall-form #login", "#login-invalid");
			var pseudo_exist = Core.Forms.PseudoExist("#edit-hall-form #pseudo","input[name=type]" ,"#pseudo-invalid");
			var password_value = $("#password").attr('value');
			var confirm_password_value = $("#confirm_password").attr('value');
			  
			if(password_value != '' || confirm_password_value != ''){
				
			   var password = Core.Forms.NotEmpty("#edit-hall-form #password", "#password-invalid");
			   var confirm_password = Core.Forms.NotEmpty("#confirm_password", "#confirm_password-invalid");
			   
				if (confirm_password) {
					var confirm_passwordEqual = Core.Forms.EqualTo("#confirm_password", "#edit-hall-form #password", "#confirm_password-invalid");
				}
				
				if (name && pseudo && login && Core.Auth.ValidPseudo && Core.Auth.ValidEmail && password && confirm_password && confirm_passwordEqual && fullname) {
						$(this).ajaxSubmit( {
				          success : function(datas) {
				            if(datas != 0){
				            	$("#content").html(datas);
				            	
				            	//etape suivante
				            	if(mode == 1){
				            		$($('.edit-buttons a').get((currentStep + 1))).click();
				            	}
				            	
				            }
				          }
				    });
				}			
				
			}else{
				//console.log('FCT : '+Core.Auth.ValidPseudo);
				if (name && pseudo && Core.Auth.ValidPseudo && Core.Auth.ValidEmail && login) {
						$(this).ajaxSubmit( {
				          success : function(datas) {
				            if(datas != 0){
				            	$("#content").html(datas);
				            	
				            	//etape suivante
				            	if(mode == 1){
				            		$($('.edit-buttons a').get((currentStep + 1))).click();
				            	}
				            	
				            }
				          }
				    });
				}
			}
			
		});

	}
}

Core.Member = {
	Initialize : function() {
		Core.Member.Edit();
		Core.Member.EditOption();
	},
	EditOption : function(){
		
		/* ADD LINK */
		$('#edit-user-form .add-link, #register-member-form .add-link').die().live('click',function(e){
			
			e.preventDefault(); 

			var data = $('input[name=link]').val();
			var url = '/Default/member/add-link';
			
			var isurl = Core.Forms.isUrl("input[name=link]", "#link-invalid");
			var link_title = Core.Forms.NotEmpty("input[name=link_title]", "#link-invalid");

			if(isurl && link_title){
				$.ajax({
					  type: 'POST',
					  url: url,
					  data: 'link='+isurl+'&link_title='+link_title,
					  success: function(idmedia){
						if(idmedia != 0){
						
						  var html = '<div class="item" style="clear:both;"><div class="media_title"><a href="'+data+'" class="notaddress" target="_blank">'+ link_title +'</a></div><div class="media_time"></div><div class="media_delete media_delete" id="deletemedia_'+ parseInt(idmedia) +'"></div><div class="clear"></div></div>';	
								
						   $('.link_list').fadeIn(function(){
							   $('.link_list').append(html);  
							   $('input[name=link]').val(' ');
							   $('input[name=link_title]').val('Titre du lien');
						   });
						
						
						}
					
					  }
				});
			}
			
		});
		
		/* ADD FILES MUSIC*/
		$('#edit-user-form .add-file,#register-member-form .add-file,').die().live('click',function(e){
			
			e.preventDefault(); 

			if($(this).parent().find("input[name='media_optin']").is(':checked')){
				$(this).parent().find('.upload-invalid').hide(function(){
					Upload.PostaFile.startUpload('multiUpload');
				});
			}else{
				$(this).parent().find('.upload-invalid').show();
			}

		});
		
		// delete media
		$('#edit-user-form .media_delete, #register-member-form .media_delete').die().live('click',function(e){
			
			e.preventDefault(); 
			
			var dom = $(this);
			url = '/Default/member/delete-media';
			var id = dom.attr('id');
			var tab = id.split('_');
			id = tab[1];
			
			//console.log(dom.parent());
			
			$.post(url, {id: id}, function(data){
					dom.parent().remove();
			});
		})
		
	},
	Edit: function(){
		
		Core.Forms.Blur("#edit-user-form #pseudo", 'Core.Forms.NotEmpty("#pseudo", "#pseudo-invalid")');
		Core.Forms.Blur("#edit-user-form #login", 'Core.Forms.NotEmpty("#edit-artist-form #login", "#login-invalid")');
		
		// On submit
		$('#edit-user-form').die().live('submit',function(e){
			
			   e.preventDefault(); 
			
			  var pseudo = Core.Forms.NotEmpty("#edit-user-form #pseudo", "#pseudo-invalid");
			  var login = Core.Forms.NotEmpty("#edit-user-form #login", "#login-invalid");
			  
			 var login_exist = Core.Forms.EmailExist("#edit-user-form #login", "#login-invalid");
				var pseudo_exist = Core.Forms.PseudoExist("#edit-user-form #pseudo","input[name=type]" ,"#pseudo-invalid");

				var password_value = $("#password").attr('value');
				var confirm_password_value = $("#confirm_password").attr('value');
			  
			if(password_value != '' || confirm_password_value != ''){
				
			   var password = Core.Forms.NotEmpty("#edit-user-form #password", "#password-invalid");
			   var confirm_password = Core.Forms.NotEmpty("#confirm_password", "#confirm_password-invalid");
			   
				if (confirm_password) {
					var confirm_passwordEqual = Core.Forms.EqualTo("#confirm_password", "#edit-user-form #password", "#confirm_password-invalid");
				};	
				
				
				if (pseudo && login && Core.Auth.ValidPseudo && Core.Auth.ValidEmail && password && confirm_password && confirm_passwordEqual) {
						$(this).ajaxSubmit( {
				          success : function(datas) {
				            if(datas != 0){
				            	$("#content").html(datas);
				            }
				          },
				          complete : function(datas) {
				        	  /*
								 * TOUJOURS DANS LE COMPLETE POUR INTERVENIR
								 * APRES SUCESS
								 */
				        	  Core.Auth.Header();
				          }
				    });
				}			
				
			}else{
				if (pseudo && Core.Auth.ValidPseudo && Core.Auth.ValidEmail && login) {
						$(this).ajaxSubmit( {
				          success : function(datas) {
				            if(datas != 0){
				            	$("#content").html(datas);
				            }
				          },
				          complete : function(datas) {
				        	  /*
								 * TOUJOURS DANS LE COMPLETE POUR INTERVENIR
								 * APRES SUCESS
								 */
				        	  Core.Auth.Header();
				          }
				    });
				}
			}
			
		});
		
		
	}
}

Core.Place = {
	Initialize : function() {
		/*
		 * $('.footer_elem').click(function(){
		 * $('.footer_elem').removeClass('selected');
		 * $(this).addClass('selected');
		 * 
		 * var id = $(this).attr('id'); var tab = id.split('_');
		 * 
		 * var elem = tab[1]; $('.footer_container').hide();
		 * $('#actu_'+elem).show(); });
		 */
	}
}

Core.Review = {
	Initialize : function() {
		Core.Review.AddReview();
		Core.Review.Review();
		Core.Review.Tab();
	},
	Tab : function(){
		$('.footer_elem').live('click',function(){
			$('.footer_elem').removeClass('selected');
			$(this).addClass('selected');
			
			var id = $(this).attr('id');
			var tab = id.split('_');
			
			var elem = tab[1];
			$('.footer_container').hide();
			$('#review_'+elem).show();
			return false;
		});
	},
	Review : function() {
		$('.review_footer_content .review_commentview .pagination_container .pagination a').die().live('click',function(e){
			e.preventDefault(); 
			var dom = $(this);
			var url = dom.attr('href');
			$.ajax( {
				type : "GET",
				url : url,
				success : function(data) {
					if(data != 0){
						dom.parent().parent().parent().html(data);
					}
				}
			});
		});	
	},
	AddReview : function() {
		$('.review_footer_content #add-review-form .send').die().live('click',function(e){
			e.preventDefault(); 
			var form = $("#add-review-form");
			
			isvalid_email = false;
			
			pseudo = $('#add-review-form .comment-pseudo').val();
			
			comment = $('#add-review-form .comment').val();
		
			if (comment != '' ) {
				valid_comment = true;
				$('#add-review-form #comment-error').css('display','none');
			}else{
				valid_comment = false;
				$('#add-review-form #comment-error').css('display','inline');
			}
			
			/*MODE*/
			var connected = $('.login-review-connected').length; 
			if (( connected != 0 && valid_comment )) {
				
				
					form.ajaxSubmit( {
				          success : function(data) {

								$('#add-review-form .comment').val('');
				            	form.parent().next('.review_commentview').children('.comment_container').html(data);
				            	
				          },
						  complete : function(){
				        	  form.parent().hide('fast',function(){
				        		  form.parent().next('.review_commentview').show('fast',function(){
				        			  form.parent().parent().prev('.review_footer').children('.comment').removeClass('selected');
				        			  form.parent().parent().prev('.review_footer').children('.comment_view').addClass('selected');
				        			  var nbr = form.parent().parent().prev('.review_footer').children('.comment_view').children('.nbr_comment').html();
				        			  form.parent().parent().prev('.review_footer').children('.comment_view').children('.nbr_comment').html(parseInt(nbr)+1);
				        		  }); 
				        	  });
				          }
				        });

				
			};
			
		
				// comment = $('#add-review-form .comment').val();
		
			return false;
		
		});
		
	},
	changeTab: function(){
		
		
		
	}
}

Core.Player = {
	booinit: true,
	mp3: [],
	playlist : [],
	currentTotal: null,
	mp3current : null,
	NextRadio : false,
	Initialize : function() {
		Core.Player.Position();
		$('.player .backward,.song_info .backward').live('click', function(e){
			e.preventDefault(); 
			thisMovie('MajesPlayer').previous();
			
			var self = $('.player .play, .song_info .play');
			self.addClass('pause');
		});
		
		$('.player .forward,.song_info .forward').live('click', function(e){
			e.preventDefault(); 
			thisMovie('MajesPlayer').next();
			
			var self = $('.player .play, .song_info .play');
			self.addClass('pause');
			
		});
		
		$('.player .play, .song_info .play, .bulle-info-play').live('click', function(e){
			//console.log('player toggle');
			var self = $('.player .play, .song_info .play, .bulle-info-play');
			e.preventDefault(); 
			thisMovie('MajesPlayer').toggle();
			
			if(self.hasClass('pause'))
				self.removeClass('pause');
			else
				self.addClass('pause');
		});
		
		$('.playlist li .icon_play').live('click',function(){
			$('.playlist li .icon_play.active').removeClass('active');
			
			var self = $(this);
			self.addClass('active');
			
			$('.player .play, .song_info .play').addClass('pause');;
		});
		
		$("#header-container .player .progress-bar").live('click', function(e){
			var self = $(this);
			var playerLeft = parseInt($('#header .user').position().left == 0 ? $('#header .user').css('margin-left') : $('#header .user').position().left);
			var progressBarLeft = this.offsetLeft + playerLeft;
			var xClick = e.pageX - progressBarLeft;
			var xClickWithinProgressBar = xClick;
			var progressBarWith = self.width();
			var percent = parseInt((xClickWithinProgressBar / progressBarWith) * 100);
			
			// alert(percent+' / ' + playerLeft)
			
			thisMovie('MajesPlayer').goto(Core.Player.currentTotal*percent/100);
			
		});
		
		$(".player_bg .progress-bar").live('click', function(e){
			var self = $(this);
			var playerLeft = parseInt($('#header .user').position().left == 0 ? $('#header .user').css('margin-left') : $('#header .user').position().left);
			var progressBarLeft = 110 + playerLeft;
			var xClick = e.pageX - progressBarLeft;
			var xClickWithinProgressBar = xClick;
			var progressBarWith = self.width();
			var percent = parseInt((xClickWithinProgressBar / progressBarWith) * 100);
			
			// alert(percent+' / ' + playerLeft)
			
			thisMovie('MajesPlayer').goto(Core.Player.currentTotal*percent/100);
			
		});
	},
	removeMp3: function(idmedia){
	//	console.log('remove mp3');
		thisMovie('MajesPlayer').removeMp3(idmedia);
	},
	reinitPlaylist: function(){
	//	console.log('reinit playlist');
		var playlist = Core.Player.mp3;
		for(var i= 0; i < playlist.length; i++)
		{
			Core.Player.removeMp3(playlist[i].idmedia);
		}
		
		Core.Player.mp3 = [];
		
	},
	addMp3: function(url_mp3, artist, title, idmedia, url_details, booplay, duration){
	//	console.log('add mp3'+ idmedia);
		
		// Verify that the mp3 is not already in the current playlist
		if ($.inArray(idmedia, Core.Player.playlist)  < 0 ) {
			Core.Player.playlist.push(idmedia);
			//console.log('Not in the playlist --> we had the mp3');
				var mp3 = [];

				mp3.push({
						url_mp3: url_mp3,
						artist: artist,
						title: title,
						idmedia: idmedia,
						url_details: url_details,
						duration: duration
					});

				Core.Player.mp3.push({
						url_mp3: url_mp3,
						artist: artist,
						title: title,
						idmedia: idmedia,
						url_details: url_details,
						duration: duration
					});
					//		console.log(mp3);
				if(booplay == true)
				{
		    		thisMovie('MajesPlayer').addMp3(mp3, true);
				//	Core.Player.playMp3(idmedia);
					if($('.player').is(':visible')){
					//	console.log('player visible');			
					}else{
					//	console.log('player not visible');			
						$('.player').slideDown();
					}
					Core.Player.Position();
				}else
			    	thisMovie('MajesPlayer').addMp3(mp3, false);
		}else{
			Core.Player.playMp3(idmedia);
			//console.log('Already in the playlist');
		}
		
	
	
		return false;
	},
	playMp3: function(idmedia)
	{
	//	console.log('play mp3');
		
		thisMovie('MajesPlayer').playMp3(idmedia);
		
		/*
		var self = $('.player .play, .song_info .play, .bulle-info-play');

		if(self.hasClass('pause')){
		}else{			
			self.addClass('pause');
			thisMovie('MajesPlayer').playMp3(idmedia);	
		}
		
		if($('.player').is(':visible')){
			console.log('player visible');			
		}else{
			console.log('player not visible');			
			$('.player').slideDown();
		}
		
		/*
		if($('.player_bg').is(':visible')){			
		}else{
			$('.player_bg').slideDown();
		}
		*/
		
		return false;
	},
	refreshPlaylist: function(mp3s, mp3)
	{
	//	console.log('refresh playlist')
		Core.Map.mp3current = mp3;
		
		
		if (Core.Player.NextRadio == true) {
			//console.log( 'Player class refreshplaylist nextradio TRUE ');
			//alert("ok");
			Core.Map.RadioChange('next', true, 'player');
			Core.Map.Mp3InProgress = true;


		};
		
		
		$('.player .music .artist,.player_bg  .song_title .artist').html(mp3.artist);
		var title = mp3.title;
	//	console.log(title.length);
		
		if ( title.length > 18  ) {
			title = title.substring(0,18)+'...';
		};
		
		$('.player .music .title,.player_bg .song_title .title').html(title);
		$('.player .link,.player_bg .link').attr('href', mp3.url_details);
		$('.player .progress-bar .time,.player_bg .progress-bar .time').html(mp3.duration);
	},
	refreshCurrent: function(mp3, loaded, total, played )
	{
		Core.Player.currentTotal = total;
		var percent = (played / total) * 100;
		$('.player .progress-bar .percent,.player_bg .progress-bar .percent, .bulle-info-progress-bar-percent').css('width', percent+'%');
	
		//document.getElementById("status").innerHTML = mp3.url_mp3 + "<br/><pre>" + played + " / " + total + " / " + loaded + "</pre>";
	},
	Position: function(){

		
				if ($("#header-container .player").css('display') != 'none'  ) {

		
					var delay = (function(){
					 var timer = 0;
					 return function(callback, ms){
					   clearTimeout (timer);
					   timer = setTimeout(callback, ms);
					 };
					})();
					//console.log($('#header-normal').length);
					if ( $('#header-normal').length != 0  ) {
						$('#header-normal').css('height','180px');
					};
					
					$(window).scroll(function(){
					
						
								var windowHeight = $(window).height();
								var documentHeight = $(document).height();
								var scrollTop = $(window).scrollTop();
								topmargin = parseInt( documentHeight) - parseInt(scrollTop) - windowHeight;						
								if ( scrollTop <= 43) {
									delta = 43 - scrollTop ;
									$('#header-container .player').css('top',delta+'px');
								}else{
									$('#header-container .player').css('top', 0);
								}
								$('#header-container .player').css('display','inline');
				
					});

				};
		
	
		$('#header-container .player').css('top','0');
		// Default position if direct access to a link with comment anchor
		var windowHeight = $(window).height();
		var documentHeight = $(document).height();
		var scrollTop = $(window).scrollTop();

		$('#header-container .player').css('top','0');
		topmargin = parseInt( documentHeight) - parseInt(scrollTop) - windowHeight;
		
		if ( scrollTop <= 43) {
			delta = 43 - scrollTop ;
			$('#header-container .player').css('top',delta+'px');
		}else{
			$('#header-container .player').css('top', 0);
		}
		
	}
}

Core.Twitter = {
	Initialize: function(){
	 $("#twitter").tweet({
	        join_text: "auto",
	        username: "espritmusique",
	        avatar_size: 48,
	        count: 6,
	        refresh_interval:3000,
	        retweets:false,
	        auto_join_text_default: "",
	        template: "{text} {time} {join}",
	        auto_join_text_ed: "we",
	        auto_join_text_ing: "we were",
	        auto_join_text_reply: "we replied",
	        auto_join_text_url: "we were checking out",
	        loading_text: "loading tweets..."
	      });
	},
	getMessages: function(username)
	{
		// assign our initial vars
	    // do a JSON request to twitters API
	    /*
		 * $.getJSON(Core.Twitter.url + username + '&count=' +
		 * Core.Twitter.count + "&callback=?", function (data) {
		 * Core.Twitter.data = data; console.log(data) });
		 */
	}
}


Core.Soundplace = {
	
	Initialize : function(){
			Core.Soundplace.Tooltip();
	},
	Tooltip : function(){
			
			$('.sp-button').mouseover(function(){
				
				buttonWidth = $('.sp-button').width()/2;
								
				width = $('.tooltip', this).width();
				position = parseInt(width/2);
				position = buttonWidth - position  ;
				position = position+'px';
				
				//console.log(position);
				
				$('.tooltip', this).css('left',position);
				$('.tooltip', this).show();
				
				$(this).parent().find('.option-show').show();			
				
			});
			
			$('.sp-button').mouseout(function(){
				$('.tooltip', this).hide();
				$(this).parent().find('.option-show').hide();
			});
			
			$('.option-click').click(function(){
					
				$(this).parent().find('.option').fadeIn(function(){
					
					$(this).mouseleave(function(){
						$(this).fadeOut();
					})
					
				});
				return false;
			})
			
	}
	
}

Core.Sounplaceradio = {
	Xml  : null,
	list : function(){
		
		var searchfield = $('#sp-search-field').attr('value');
		var alt = $('#sp-search-field').attr('alt');
		if (searchfield == alt) {
			searchfield = '';
		}else{
			$('.search-cancel').css('display','inline');
		}
		
		var idartist_category = $('#idartist_category').attr('value');
		
		$.ajax({
		  url: '/sound/markers/',
		  type: 'POST',
		  dataType: 'xml',
			async : true,
		  data: {lat: Core.MapValues.CenterLatitude, lng : Core.MapValues.CenterLongitude, zoom : Core.MapValues.Zoom, type: idartist_category, category : Core.MapValues.CurrentCategory, search : searchfield} ,
		  complete: function(xhr, textStatus) {
		    //called when complete
		  },
		  success: function(data, textStatus, xhr) {
		   
				Core.Sounplaceradio.Xml = data;

				//	Default hide markers
				//	Core.Map.HideMarkers('scene');

		  },
		  error: function(xhr, textStatus, errorThrown) {
		    //called when there is an error
		  }
		});
		
		
	}
	
}

// For multiple instances with common navigation
Core.MapValues = {
	
	CenterLatitude : 48.856667, // paris
	CenterLongitude : 2.350833, // paris
	Zoom : 12,
	CurrentCategory : ''
	
}

Core.Map = {
	
	UserGeolocDone : null,
	UserGeolocImage : '/img/front/soundplace/geoloc.png',
	UserGeolocLatitude: null,
	UserGeolocLongitude: null,
	CenterLatitude : 48.856667, // paris
	CenterLongitude : 2.350833, // paris
	Zoom : 12,
	MapObject : null,
	gmarkers : null,
	gmarkersSmallMap : new Array(),
	gmarkersFullscreenMap : new Array(),
	showmap : null,
	XmlMarkers : null,
	CurrentCategory : '',
	CurrentArtist : '',
	PlaylistCurrentIndex : null,
	Playlist : null,
	StartRadioIndex : 0,
	Mp3InProgress : false,
	MarkersRequest : '',
	iframe: false,
	MapCSS : [ { featureType: "landscape.man_made", elementType: "all", stylers: [ { saturation: -99 } ] },{ featureType: "road.highway", elementType: "all", stylers: [ { lightness: 38 }, { hue: "#ff0000" }, { saturation: -94 } ] },{ featureType: "road.arterial", elementType: "all", stylers: [ { saturation: -94 }, { hue: "#ff0000" }, { lightness: 42 } ] },{ featureType: "landscape.man_made", elementType: "all", stylers: [ { lightness: 30 } ] },{ featureType: "landscape", elementType: "all", stylers: [ { saturation: -100 }, { lightness: 36 } ] },{ featureType: "water", elementType: "all", stylers: [ { hue: "#0099ff" }, { saturation: 33 } ] },{ featureType: "landscape", elementType: "all", stylers: [ { visibility: "off" } ] },{ featureType: "poi", elementType: "all", stylers: [ { saturation: -54 }, { gamma: 1.26 }, { lightness: 31 } ] },{ featureType: "all", elementType: "all", stylers: [ ] } ],
	
	Initialize : function(selector){
			//	var player = Core.Player;
			/*
			if (Core.Map.Mp3InProgress == true) {
				thisMovie('MajesPlayer').toggle();
			};
			*/			
			
			/*
			if (selector == null) {
				var selector = 'sp-map';
				Core.Player.reinitPlaylist();
			};
			*/	
			  //Set show parameter to true
			  Core.Map.showmap = true;
				
				//var map, actual, iw;
	 			//var gmarkers = [];

			  var map, actual, iw;
			//  Core.Map.gmarkers = gmarkers = [];
		 	 // Core.Map.gmarkersSmallMap = gmarkers = [];
		 	 // Core.Map.gmarkersFullscreenMap = gmarkers = [];

			  var g = google.maps;
			  var opts_map = {
				// Paris
			    center: new g.LatLng( Core.MapValues.CenterLatitude,Core.MapValues.CenterLongitude),
			    zoom: Core.Map.Zoom,
				minZoom : 5,
				tilt : 45,				
			 	disableDefaultUI: true,
			    mapTypeId: g.MapTypeId.ROADMAP,	
				
			  mapTypeControlOptions: {
			    mapTypeIds: [ g.MapTypeId.HYBRID, 'espritmusique']
			  },
			  navigationControlOptions: {
			     style: g.NavigationControlStyle.ZOOM_PAN
			  }};
			
			

			 		var styledMapOptions = { name: "espritmusique" }
			  		var CEMMapType = new google.maps.StyledMapType( Core.Map.MapCSS, styledMapOptions );
					
			
				// Small home map
				if ($("#soundplace").length == 0 ) {

					try{
						_gaq.push(['_trackPageview', '/soundplace/petite-carte']);
					}catch($e){}

					var selector = 'sp-map';
			  		Core.Map.MapObject = map = new g.Map(document.getElementById(selector), opts_map);
			  		map.mapTypes.set('espritmusique', CEMMapType);
			  		map.setMapTypeId('espritmusique');
			
					// To display without user geolocalisation
					Core.Map.DisplayMarkers('small',map,Core.MapValues.CenterLongitude,Core.MapValues.CenterLatitude, Core.MapValues.Zoom);
				
					$('#smp-footer .click-relocate').die().live('click',function(){
						
						$('#small-soundplace .message-box-text').html("Nous tentons de vous localiser.<br/>Merci de bien vouloir patienter...");
						$("#small-soundplace .message-box,#small-soundplace #be-localized").fadeIn();
						var	data = $(this).metadata();
						if (this.UserGeolocDone) {
							map.setCenter(new google.maps.LatLng(data.longitude,data.latitude), 7);
						}else{
							Core.Map.UserGeoloc(map);
							map.setCenter(new google.maps.LatLng(data.longitude,data.latitude), 7);
						}
						if (infoBubble.isOpen()) {
							infoBubble.close(this.MapObject);				
						}
							return false;
					});
					
					$('#smp-footer a.click-zoomin').die().live('click',function(){
						map.setZoom(parseInt(map.getZoom())+1);
						Core.Map.Zoom = parseInt(map.getZoom())+1;
						return false;
					});

					$('#smp-footer a.click-zoomout').die().live('click',function(){
						map.setZoom(parseInt(map.getZoom())-1);
						Core.Map.Zoom = parseInt(map.getZoom())-1;
						return false;
					});
					
					
					Core.Map.Buttons(map, '#small-soundplace #smp-footer');
					
					if(Core.Map.UserGeolocDone){
						
					      initialLocation = new google.maps.LatLng( Core.Map.UserGeolocLatitude , Core.Map.UserGeolocLongitude  );
						  var marker = new google.maps.Marker({
						      position: initialLocation, 
						      map: map, 
						      title:"Ma position",
							  icon: Core.Map.UserGeolocImage,
							  id: 0
						  });		
					}

					$("#small-soundplace .smp-header #sp-search-form").die().live('submit', function(){
						Core.Map.ClearMarkers(Core.Map.gmarkersSmallMap);
						Core.Map.Search(map, Core.Map.gmarkersSmallMap);
						if (infoBubble.isOpen()) {
							infoBubble.close(this.MapObject);				
						}
						return false;
					});
					
					
					$("#small-soundplace .smp-header #sp-search-form .search-cancel").die().live('click', function(){
						$('.search-empty').fadeOut();
						$('#small-soundplace .smp-header #sp-search-form #sp-search-field').attr('value', '');
						$(this).css('display','none');
						Core.Map.ClearMarkers(Core.Map.gmarkersSmallMap);
						Core.Map.Search(map, Core.Map.gmarkersSmallMap);
						if (infoBubble.isOpen()) {
							infoBubble.close(this.MapObject);				
						}
						return false;
					});
					
				

					google.maps.event.addListener(map, 'mouseup', function() {
						delay(function(){							
							Core.Map.ClearMarkers(Core.Map.gmarkersSmallMap);							
							Core.Map.UpdateMarkerFeed( map, 'small' , Core.Map.gmarkersSmallMap );
							if (infoBubble.isOpen()) {
								infoBubble.close(this.MapObject);				
							}
						}, 500);
					});
					
					
					google.maps.event.addListener(map, 'zoom_changed', function() {
					   	delay(function(){
						Core.Map.ClearMarkers(Core.Map.gmarkersSmallMap);
						Core.Map.UpdateMarkerFeed( map, 'small' , Core.Map.gmarkersSmallMap );	
						if (infoBubble.isOpen()) {
							infoBubble.close(this.MapObject);				
						}
						}, 500);
					});
					
					$('a.soundplace-filter').die().live('click',function(){

						// Core.Map.StartRadioIndex is reinitialized
						Core.Map.StartRadioIndex = '';					

						var data = $(this).metadata();
						var category = Core.MapValues.CurrentCategory = data.class_name;

						Core.Map.ClearMarkers(Core.Map.gmarkersSmallMap);

						$('#home-map, #soundplace').append('<div class="loader-ajax-medium loader-ajax" ></div>');

						$('.bulle').fadeOut();

						// Set main object preferences
						Core.MapValues.CenterLongitude = map.getCenter().lng();
						Core.MapValues.CenterLatitude = map.getCenter().lat();
						Core.MapValues.Zoom = map.getZoom();

						Core.Map.DisplayMarkers( 'small' , map , map.getCenter().lat() ,map.getCenter().lng() , map.getZoom() );
						if (infoBubble.isOpen()) {
							infoBubble.close(this.MapObject);				
						}
						return false;
					});
					
				}else{
					//console.log(selector);
					try{
						_gaq.push(['_trackPageview', '/soundplace/carte-plein-ecran']);
					}catch($e){}
					
			  		Core.Map.MapObject = mapFullscreen = new g.Map(document.getElementById(selector), opts_map);
			  		mapFullscreen.mapTypes.set('espritmusique', CEMMapType);
			  		mapFullscreen.setMapTypeId('espritmusique');
					
					// To display without user geolocalisation
				
					Core.Map.DisplayMarkers('fullscreen',mapFullscreen,Core.MapValues.CenterLongitude,Core.MapValues.CenterLatitude, Core.MapValues.Zoom);
					
						$('#sp-footer .click-relocate').die().live('click',function(){
							
							$('#soundplace .message-box-text').html("Nous tentons de vous localiser.<br/>Merci de bien vouloir patienter...");
							$("#soundplace .message-box,#soundplace #be-localized").fadeIn();
							
							var	data = $(this).metadata();

							if (this.UserGeolocDone) {
								//console.log('geoloc is true');
								mapFullscreen.setCenter(new google.maps.LatLng(data.longitude,data.latitude), 7);
							}else{
								//console.log('geoloc starts now')
								Core.Map.UserGeoloc(mapFullscreen);
								mapFullscreen.setCenter(new google.maps.LatLng(data.longitude,data.latitude), 7);
							}
							if (infoBubble.isOpen()) {
								infoBubble.close(this.MapObject);				
							}
							return false;
						});
						
						$('#sp-footer a.click-zoomin').die().live('click',function(){
							mapFullscreen.setZoom(parseInt(mapFullscreen.getZoom())+1);
							return false;
						});

						$('#sp-footer a.click-zoomout').die().live('click',function(){
							mapFullscreen.setZoom(parseInt(mapFullscreen.getZoom())-1);
							return false;
						});
						
						google.maps.event.addListener(mapFullscreen, 'zoom_changed', function() {
						   	delay(function(){
							Core.Map.ClearMarkers(Core.Map.gmarkersFullscreenMap);
							Core.Map.UpdateMarkerFeed( mapFullscreen, 'fullscreen' , Core.Map.gmarkersFullscreenMap );	
							if (infoBubble.isOpen()) {
								infoBubble.close(this.MapObject);				
							}
							}, 500);
						});
						
						Core.Map.Buttons(mapFullscreen, '#soundplace #sp-footer');
						
						if(Core.Map.UserGeolocDone){
							
						      initialLocation = new google.maps.LatLng( Core.Map.UserGeolocLatitude , Core.Map.UserGeolocLongitude  );
							  var marker = new google.maps.Marker({
							      position: initialLocation, 
							      map: mapFullscreen, 
							      title:"Ma position",
								  icon: Core.Map.UserGeolocImage,
								  id: 0
							  });
							
						}
						
						$("#soundplace #sp-footer #sp-search-form").die().live('submit', function(){
							Core.Map.ClearMarkers(Core.Map.gmarkersFullscreenMap);
							Core.Map.Search(mapFullscreen, Core.Map.gmarkersFullscreenMap);
							if (infoBubble.isOpen()) {
								infoBubble.close(this.MapObject);				
							}
							return false;
						});
					
						$("#soundplace #sp-footer #sp-search-form .search-cancel").die().live('click', function(){
							$('#soundplace #sp-footer #sp-search-form #sp-search-field').attr('value', $('#soundplace #sp-footer #sp-search-form #sp-search-field').attr('alt'));
							$('.search-empty').fadeOut();
							$(this).css('display','none');
							Core.Map.ClearMarkers(Core.Map.gmarkersFullscreenMap);
							Core.Map.Search(mapFullscreen, Core.Map.gmarkersFullscreenMap);
							if (infoBubble.isOpen()) {
								infoBubble.close(this.MapObject);				
							}
							return false;
						});
						
						google.maps.event.addListener(mapFullscreen, 'mouseup', function() {
							delay(function(){
								Core.Map.ClearMarkers(Core.Map.gmarkersFullscreenMap);
								Core.Map.UpdateMarkerFeed( mapFullscreen, 'fullscreen' , Core.Map.gmarkersFullscreenMap );
								if (infoBubble.isOpen()) {
									infoBubble.close(this.MapObject);				
								}
							}, 500);
						});
						
						
						$('a.soundplace-map-filter').die().live('click',function(){

							// Core.Map.StartRadioIndex is reinitialized
							Core.Map.StartRadioIndex = '';

							var data = $(this).metadata();
							var category = Core.MapValues.CurrentCategory = data.class_name;

							Core.Map.ClearMarkers(Core.Map.gmarkersFullscreenMap);

							$('#home-map, #soundplace').append('<div class="loader-ajax-medium loader-ajax" ></div>');

							$('.bulle').fadeOut();

							// Set main object preferences
							Core.MapValues.CenterLongitude = mapFullscreen.getCenter().lng();
							Core.MapValues.CenterLatitude = mapFullscreen.getCenter().lat();
							Core.MapValues.Zoom = mapFullscreen.getZoom();

							Core.Map.DisplayMarkers( 'fullscreen' , mapFullscreen , mapFullscreen.getCenter().lat() ,mapFullscreen.getCenter().lng() , mapFullscreen.getZoom() );


							//Core.Map.UpdateMarkerFeed( map_instance, map_selector , markersArray );

							return false;
						});
						
				}

				//	Core.Map.UserGeoloc(map);

					var delay = (function(){
					  var timer = 0;
					  return function(callback, ms){
					    clearTimeout (timer);
					    timer = setTimeout(callback, ms);
					  };
					})();
				
				
				// Sort function
				// Radio
				$('a.soundplace-radio-filter').die().live('click', function(){
					
					// empty Playlist
					//Core.Player.reinitPlaylist();
					
					Core.Player.NextRadio = false;
					
					var data = $(this).metadata();
					var category = data.class_name;
					//console.log(data.class_name);
					
						if (category != '') {
							// One specific categories
							//console.log(category );
							select = "marker[type='artist'][category='"+category+"']";
							var markerSelect = $(Core.Map.XmlMarkers).find(select);
							var markerTotal = markerSelect.length;
						}else{
							// all categories
							var markerSelect = $(Core.Map.XmlMarkers).find("marker[type='artist']");
							var markerTotal = markerSelect.length;	
						}
						
						$i = 0;
						Core.Map.Playlist = new Array();
						
						StartRadioIndex = 0;
						
						markerSelect.each(function(index,element){
								Core.Player.NextRadio = false;
								//console.log(index);
								// The playlist regarding the filters (categories and type)
								Core.Map.Playlist[$i] = element;
						
								
								
								if ( ! $('.sp-footer-player .play').hasClass('pause')  ) {
									
									$('.sp-footer-player .play').addClass('pause');
								};
								
								if (index == StartRadioIndex ) {
									//Set Current Index in the playlist
									Core.Map.PlaylistCurrentIndex = index;
									idmedia = $(element).attr('idmedia_mp3');
									
									$('.artist-link').attr('href',  $(element).attr('url_content')  );

									image = '<img src="'+$(element).attr('url_photo')+'" alt="'+$(element).attr('name')+'" class="sp-artist-image" />';
									shadow ='<img id="sp-radio-shadow" src="/img/front/soundplace/image-shadow.png" alt="" />';
									dots =	'<img id="sp-radio-dot"  alt="" />';

									$('.music .artist, .remain-letter ').html($(element).attr('name'));
									$('.music .title').html($(element).attr('title_mp3'));
									$('.sp-radio-artist').html( image+shadow+dots);
									$('.sp-artist-image').load(function() {
										$('.loader-ajax-medium').remove();
								       	$("#soundplace .artist-name").fadeTo(0,0).css('visibility','visible').fadeTo(400,1);
										Core.Map.Play('#bulle-info-play'+$(element).attr('index'),$(element).attr('filename_mp3'), $(element).attr('name'), $(element).attr('title_mp3'), $(element).attr('idmedia_mp3'), $(element).attr('artist_url'), true,  $(element).attr('duration'));
										
										Core.Map.Mp3InProgress = true;
								    });

									$('.artist-radio').attr('href', $(element).attr('url_content'));
									$('.comment-radio').attr('href', $(element).attr('url_content')+'/voir-commentaire');
									$('.date-radio').attr('href', $(element).attr('url_content'));
									$('.artist-radio, .comment-radio').attr('onclick', 'Core.Map.Link(\''+$(element).attr('url_content')+'\')' );

									$("#sp-controls").css('height', $(window).height()-54+'px');
									$("#soundplace .artist-name").css('height', $(window).height()-54+'px');

								}
								
								
								$i++;
							
						});
					
							if ($i == parseInt(markerTotal)) {
								// Tel the player to display next artist when end of track is reached
								$(this).oneTime('3s', function(){
									Core.Player.NextRadio = true;
									//console.log('Nextradio activated');
								});
								
							};
					
				});
		
	},
	RadioChange : function(movement, playnextmp3, triggerfrom){

					//console.log('radiochange');

					//console.log('Playlist current index'+Core.Map.PlaylistCurrentIndex);

					TotalArtistList = Core.Map.Playlist.length;
					//console.log('totalArtist'+TotalArtistList);

					PlaylistCurrentIndex = Core.Map.PlaylistCurrentIndex;
					SavedPlaylistCurrentIndex = Core.Map.PlaylistCurrentIndex;
					windowwidth = $(window).width();

					$('#sp-controls').append('<div class="loader-ajax-medium"></div>');
					$("#soundplace .artist-name").css('visibility', 'hidden');
					//console.log('Before: '+PlaylistCurrentIndex);
					if (movement == 'next') {

						//PlaylistCurrentIndex = PlaylistCurrentIndex+1
						if (PlaylistCurrentIndex >= TotalArtistList-1) {
							PlaylistCurrentIndex = 0;
						}else{
							PlaylistCurrentIndex = PlaylistCurrentIndex+1;
						}

						// ADD the new right image element
						suffix = 'right';

						rightElem = '<div class="sp-radio-artist sp-radio-artist-right" style="left:'+windowwidth+'px"></div>';
						$('#soundplace').append(rightElem);

					}else if(movement == 'previous'){
						//PlaylistCurrentIndex = PlaylistCurrentIndex-1;
						if (PlaylistCurrentIndex <= 0) {
							PlaylistCurrentIndex = TotalArtistList-1;
						}else{
							PlaylistCurrentIndex = PlaylistCurrentIndex-1;
						}

						// ADD the new right image element
						suffix = 'left';
						leftElem = '<div class="sp-radio-artist sp-radio-artist-left" style="left:-'+windowwidth+'px"></div>';
						$('#soundplace').append(leftElem);
					}	

						


						Core.Map.PlaylistCurrentIndex = parseInt(PlaylistCurrentIndex);
						//console.log('Radio change After: PlaylistCurrentIndex '+PlaylistCurrentIndex);			

						

						self =  $(Core.Map.Playlist[PlaylistCurrentIndex]) ;
						
						
						

/*
						$('.artist-link-concat').each(function(indexLink, elementLink) {
						  			//attr('href',  self.attr('url_content')  );
						    $(elementLink).attr( 'href' , $(elementLink).attr('href')+self.attr('url_content') );

						});
*/
						image = '<img src="'+self.attr('url_photo')+'" alt="'+self.attr('name')+'" class="sp-artist-image" />';
						shadow ='<img id="sp-radio-shadow" src="/img/front/soundplace/image-shadow.png" alt="" />';
						dots =	'<img id="sp-radio-dot"  alt="" />';



						$('.artist-radio').attr('href', self.attr('url_content'));
						$('.comment-radio').attr('href', self.attr('url_content')+'/voir-commentaire');
						$('.date-radio').attr('href', self.attr('url_content'));
						
					

						$('.music .artist, .remain-letter ').html(self.attr('name'));
						try{
							_gaq.push(['_trackPageview', '/soundplace/mode-radio/'+self.attr('name')]);
						}catch($e){}
						$('.music .title').html(self.attr('title_mp3'));

						$('.sp-radio-artist-'+suffix).html( image+shadow+dots);
						$('.sp-artist-image').load(function() {
							if (playnextmp3 == false) {
								//console.log( 'play next radio change ==> ' + movement );
								idmedia_mp3 = self.attr('idmedia_mp3');
								// deactivate next track on end
								Core.Player.NextRadio = false;
								// Play the mp3
								Core.Map.Play('#bulle-info-play'+self.attr("index"),self.attr("filename_mp3"), self.attr("name"), self.attr("title_mp3"), self.attr("idmedia_mp3"), self.attr("url_content"), true, self.attr("duration"));

								// Reactivate auto next track on end
								Core.Player.NextRadio = true;
							}


							$('.loader-ajax-medium').remove();

							$("#sp-controls").css('height', $(window).height()-54+'px');
							$("#soundplace .artist-name").css('height', $(window).height()-54+'px');

							if (movement == 'next') {

								//console.log("next music");

								$('.sp-radio-artist-center').animate({left:-windowwidth+'px'});
								$('.sp-radio-artist-right').animate({left:0},function(){
										$(".artist-name").css('height', $(window).height()-54+'px');
									    $("#soundplace .artist-name").fadeTo(0,0).css('visibility','visible').fadeTo(400,1);
										$('.sp-radio-artist-center').remove();
										$(this).addClass('sp-radio-artist-center');
										$(this).removeClass('sp-radio-artist-right');
									});	
									//console.log(Core.Player.playlist);
									//console.log($.inArray( self.attr('idmedia_mp3') , Core.Player.playlist ));
									if ($.inArray( self.attr('idmedia_mp3') , Core.Map.Playlist ) < 0) {
										
											//console.log('Add in playlist');
											NextMP3Index = parseInt(SavedPlaylistCurrentIndex) + 2;
											if (NextMP3Index >= TotalArtistList) {
												NextMP3Index = 0;
											}
											//console.log( 'Radiochange prepare next' + NextMP3Index );
											self =  $(Core.Map.Playlist[NextMP3Index]) ;
											//console.log(self.attr('name'));
											Core.Player.addMp3(self.attr('filename_mp3'), self.attr('name'), self.attr('title_mp3'), self.attr('idmedia_mp3'), self.attr('artist_url'), false,  self.attr('duration'));
											image = '<img src="'+self.attr('url_photo')+'" alt="'+self.attr('name')+'" class="image-cache" style="display:none" />';
										
											$("#image-cache").html(image)
											
									};
									
									
									



							}else if(movement == 'previous'){
								//console.log("previous music");

									$('.sp-radio-artist-center').animate({left:windowwidth+'px'});

									$('.sp-radio-artist-left').animate({left:0}, function(){
										$(".artist-name").css('height', $(window).height()-54+'px');
										$("#soundplace .artist-name").fadeTo(0,0).css('visibility','visible').fadeTo(400,1);
										$('.sp-radio-artist-center').remove();
										$(this).addClass('sp-radio-artist-center');
										$(this).removeClass('sp-radio-artist-left');
									});

							}

/*
							if (triggerfrom == 'click') {
								Core.Player.NextRadio = true;
									NextMP3Index = parseInt(SavedPlaylistCurrentIndex) + 2;
									if (NextMP3Index >= TotalArtistList) {
										NextMP3Index = 0;
									}
									//console.log( 'Radiochange prepare next' + NextMP3Index );
									self =  $(Core.Map.Playlist[NextMP3Index]) ;
									//console.log(self.attr('name'));
									Core.Player.addMp3(self.attr('filename_mp3'), self.attr('name'), self.attr('title_mp3'), self.attr('idmedia_mp3'), self.attr('artist_url'), false,  self.attr('duration'));
							}else{
								console.log(triggerfrom);
							}
*/
							
					    });

			
	},
	UpdateMarkerFeed : function(map_instance, map_css_selector , markersArray){
		$('#home-map, #soundplace').append('<div class="loader-ajax-medium loader-ajax" ></div>');
		
		// Wether it is the small map or the fullscreen one
		if ($("#soundplace").length == 0 ) {
			var map_css_selector = 'small';
		//	console.log('small');
		}else{
		//	console.log('fullscreen');
			var map_css_selector = 'fullscreen';			
		}
			
		$('.bulle').fadeOut();
		
		// Set main object preferences
		Core.MapValues.CenterLongitude = map_instance.getCenter().lng();
		Core.MapValues.CenterLatitude = map_instance.getCenter().lat();
		Core.MapValues.Zoom = map_instance.getZoom();
		
		Core.Map.DisplayMarkers( map_css_selector , map_instance , map_instance.getCenter().lat() ,map_instance.getCenter().lng() , map_instance.getZoom() );
		
	},
	ClearMarkers : function(markersArray){
		if (markersArray) {
		    for (i in markersArray) {
				try{
			      	markersArray[i].setMap(null);
				}
				catch(err){}
				}
		}
	},
	Buttons : function(map, selector){
		// Buttons
		//	console.log(selector + ' a.click-fullscreen')
		$(selector + ' a.click-fullscreen').die().live('click', function(){
			infoBubble.close(map);
			$("#sound-lightboxOverlay").html('<div class="loader-ajax-medium"></div>').css('display','block');
			$("#content").css('display','none');
			$("#sound-lightboxContent").load($(this).attr('href'),
			 function(){
				Core.Soundplace.Tooltip();
				
					$('#sound-lightbox').css('display','block');
					$("#soundplace").css( {'width': $(window).width() , 'height': $(window).height() } );
					tt = Core.Map;
					tt.Initialize("sp-map-big");
					google.maps.event.trigger(this, "resize");
				
					$(window).resize(function() {
						
						$("#soundplace").css( {'width': $(window).width() , 'height': $(window).height() } );
						google.maps.event.trigger(this, "resize");
				});
					
			
			});
			return false;
			
		});
		
		// Buttons@
		$(selector + ' a.click-radio').die().live('click', function(){
			
			try{
				_gaq.push(['_trackPageview', '/soundplace/mode-radio']);
			}catch($e){}
			
			
			//Core.Map.Playlist = null;
			
			$("#sound-lightboxContent #soundplace").remove();
			$("#content").css('display','none');
			$("#footer").css('display','none');
			$("#sound-lightboxOverlay").css('display','block');
		//	$('#sp-controls').append('<div class="loader-ajax-medium"></div>');
			
			$("#sound-lightboxContent").load($(this).attr('href'), { category: Core.MapValues.CurrentCategory, artist : Core.Map.CurrentArtist  },function(){
			//console.log($(this).attr('href'));
				Core.Soundplace.Tooltip();
				$("#sound-lightboxOverlay").css('display','block');
				
					$('#sound-lightbox').css('display','block');
					
					if (isNaN(Core.MapValues.CurrentCategory)) {
						Core.MapValues.CurrentCategory = '';
					};
				
					
						var searchfield = $('#sp-search-field').attr('value');
						var alt = $('#sp-search-field').attr('alt');
						if (searchfield == alt) {
							searchfield = '';
						}else{
							$('.search-cancel').css('display','inline');
						}

						var idartist_category = $('#idartist_category').attr('value');

						$.ajax({
						  url: '/sound/markers/',
						  type: 'POST',
						  dataType: 'xml',
							async : true,
						  data: {lat: Core.MapValues.CenterLatitude, lng : Core.MapValues.CenterLongitude, zoom : Core.MapValues.Zoom, type: idartist_category, category : Core.MapValues.CurrentCategory, search : searchfield} ,
						  complete: function(xhr, textStatus) {
						    //called when complete
						  },
						  success: function(data, textStatus, xhr) {
									
									var markerSelect = Core.Sounplaceradio.Xml = data;
									var markerTotal = markerSelect.length;
									
									
									if (Core.MapValues.CurrentCategory != '') {
										// One specific categories
										select = "marker[type='artist'][category='"+Core.MapValues.CurrentCategory+"']";
										var markerSelect = $(Core.Map.XmlMarkers).find(select);
										var markerTotal = markerSelect.length;
									}else{
										// all categories
										var markerSelect = $(Core.Map.XmlMarkers).find("marker[type='artist']");
										var markerTotal = markerSelect.length;	
										//console.log('all categories --> total '+ markerTotal);
									}
									
									
									var i = 0;
									Core.Map.Playlist = new Array();
									
									if (Core.Map.StartRadioIndex == 0) {
										StartRadioIndex = 0;
									}else{
										StartRadioIndex = Core.Map.StartRadioIndex;
									};
									
									
									NextStartRadioIndex = parseInt(StartRadioIndex)+1;
									if (NextStartRadioIndex >= markerTotal-1) {
										NextStartRadioIndex = 0;
									};
									
									markerSelect.each(function(index,element){

											
											
											// The playlist regarding the filters (categories and type)
											Core.Map.Playlist[i] = element;

											if (index == StartRadioIndex ) {
												//console.log('index '+ index+' - StartRadioIndex '+ StartRadioIndex);
												//Set Current Index in the playlist
												
												Core.Map.PlaylistCurrentIndex = parseInt(StartRadioIndex);
												
												//console.log('Core.Map.PlaylistCurrentIndex at initialisation + '+ Core.Map.PlaylistCurrentIndex);
												idmedia = $(element).attr('idmedia_mp3');
												Core.Map.Play('#bulle-info-play'+$(element).attr('index'),$(element).attr('filename_mp3'), $(element).attr('name'), $(element).attr('title_mp3'), $(element).attr('idmedia_mp3'), $(element).attr('url_content'), true,  $(element).attr('duration'));

												Core.Map.Mp3InProgress = true;
												image = '<img src="'+$(element).attr('url_photo')+'" alt="'+$(element).attr('name')+'" class="sp-artist-image" />';
												shadow ='<img id="sp-radio-shadow" src="/img/front/soundplace/image-shadow.png" alt="" />';
												dots =	'<img id="sp-radio-dot"  alt="" />';

												$('.music .artist, .remain-letter ').html($(element).attr('name'));
												
												try{
													_gaq.push(['_trackPageview', '/soundplace/mode-radio/'+$(element).attr('name')]);
												}catch($e){}
												
												
												$('.music .title').html($(element).attr('title_mp3'));
												$('.sp-radio-artist').html( image+shadow+dots);
												$('.sp-artist-image').load(function() {
													$('.loader-ajax-medium').remove();
											       	$("#soundplace .artist-name").fadeTo(0,0).css('visibility','visible').fadeTo(400,1);
											    });

												$('.comment-radio').attr('href', $(element).attr('url_content')+'/voir-commentaire');
												$('.date-radio').attr('href', $(element).attr('url_content'));
												$('.artist-radio').attr('href', $(element).attr('url_content'));

												$("#sp-controls").css('height', $(window).height()-54+'px');

												$('.favorite').attr('href', '/artiste-favoris/'+$(element).attr('id'));

											}
											
											if(index == NextStartRadioIndex){
												//console.log('add next to player' + $(element).attr('name'));
												
												//	addMp3: function(url_mp3, artist, title, idmedia, url_details, booplay, duration){
												Core.Player.addMp3($(element).attr('filename_mp3'), $(element).attr('name'), $(element).attr('title_mp3'), $(element).attr('idmedia_mp3'), $(element).attr('artist_url'), false,  $(element).attr('duration'));
												Core.Player.NextRadio = true;
												image = '<img src="'+$(element).attr('url_photo')+'" alt="'+$(element).attr('name')+'" style="display:none" class="image-cache" />';
											
												$("#image-cache").html(image)
												//return false;
											}
											
											/*
											if (i == parseInt(markerTotal-1)) {
												// Tel the player to display next artist when end of track is reached
												//console.log("Next radio to true");
												Core.Player.NextRadio = true;
											};
											*/

											i++;

									});
										
									
									$(".artist-name").css('height', $(window).height()-54 +'px');
									$(window).resize(function() {
										$("#sp-controls").css('height', $(window).height()-54 +'px');
										$(".artist-name").css('height', $(window).height()-54 +'px');
										//console.log($(window).height());
									});



									$('a.next-artist,.sp-forward').die().live('click', function(){
										Core.Map.RadioChange('next',false,'click');
										return false;

									});

									$( 'a.previous-artist,.sp-backward').die().live('click', function(){
										Core.Map.RadioChange('previous',false,'click');
										return false;

									});
									
									$('.normal-link').die().live('click', function(){
										href = $(this).attr('href');											
										$("#content").css('display','block');
										$("#footer").css('display','block');
										$("#sound-lightboxOverlay").css('display','none');
										$("#sound-lightbox").fadeOut(function(){	
											$("#soundplace").remove();	
										});
										return false;
									});

						  },
						  error: function(xhr, textStatus, errorThrown) {
						    //called when there is an error
						  }
						});
					
					
					
				

					
				});
		
			return false;
			
		});
		


	
		
		$(selector + '.bulle-info-play').die().live('click', function(){
			var data = $(this).metadata();
			$('.buttons-mode .radio').attr('data', '{ idartist : \''+data.idartist+'\’ }');
			
		});
		
		$(selector + 'a.click-zoomin').die().live('click',function(){
			map.setZoom(parseInt(map.getZoom())+1);
			return false;
		});
		
	},			
	UserGeoloc : function(map, callback){


		image = Core.Map.UserGeolocImage;
		
		var browserSupportFlag =  new Boolean();
		
		if(navigator.geolocation) {
		    browserSupportFlag = true;
		    navigator.geolocation.getCurrentPosition(function(position) {
			  userLat = position.coords.latitude;
			  userLon = position.coords.longitude;
			  Core.Map.UserGeolocLatitude = position.coords.latitude;
			  Core.Map.UserGeolocLongitude = position.coords.longitude;
		      initialLocation = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);
			  var marker = new google.maps.Marker({
			      position: initialLocation, 
			      map: map, 
			      title:"user",
				  icon: image,
				  id: 0
			  });
				// Geoloc has been done once
				Core.Map.UserGeolocDone = true;
				$('.click-relocate, .click-radio').attr('data' , "{longitude: '"+Core.Map.UserGeolocLatitude+"', latitude: '"+Core.Map.UserGeolocLongitude+"'}" );
				Core.MapValues.CenterLatitude = Core.Map.UserGeolocLatitude;
				Core.MapValues.CenterLongitude = Core.Map.UserGeolocLongitude;
				// Core.Map.DisplayMarkers(map,this.UserGeolocLatitude,this.UserGeolocLongitude);
				map.setZoom(12);
		        map.setCenter(initialLocation);
		
				//	alert('1. navigator geolocation success');
					
				$(".message-box,  .loader-ajax-medium").fadeOut();
		    }, function() {
				//Core.Map.DisplayMarkers(map,Core.Map.UserGeolocLatitude,Core.Map.UserGeolocLongitude);
			//	alert('navigator.geoloc: '+browserSupportFlag);
		        handleNoGeolocation(browserSupportFlag);
			//	alert('1. navigator geolocation failed');
		    });
		  // Try Google Gears Geolocation
		  } else if (google.gears) {
		    browserSupportFlag = true;
		    var geo = google.gears.factory.create('beta.geolocation');
		    geo.getCurrentPosition(function(position) {
			  userLat = position.latitude;
			  userLon = position.longitude;
			  Core.Map.UserGeolocLatitude = position.coords.latitude;
			  Core.Map.UserGeolocLongitude = position.coords.longitude;
		      initialLocation = new google.maps.LatLng(position.latitude,position.longitude);
			  var marker = new google.maps.Marker({
			      position: initialLocation, 
			      map: map, 
			      title:"user",
				  icon: image,
				  id: 0
			  });
				// Geoloc has been done once
				this.UserGeolocDone = true;
				$('.click-relocate, .click-radio').attr('data' , "{longitude: '"+Core.Map.UserGeolocLatitude+"', latitude: '"+Core.Map.UserGeolocLongitude+"'}" );
				Core.MapValues.CenterLatitude = Core.Map.UserGeolocLatitude;
				Core.MapValues.CenterLongitude = Core.Map.UserGeolocLongitude;
				//Core.Map.DisplayMarkers(map,this.UserGeolocLatitude,this.UserGeolocLongitude);
				map.setZoom(12);
		      	map.setCenter(initialLocation);
			//	alert('2. Google gears success');
				
				$(".message-box,  .loader-ajax-medium").fadeOut();
		    }, function() {
				
				//Core.Map.DisplayMarkers(map,this.UserGeolocLatitude,this.UserGeolocLongitude);
				//alert('google gear.geoloc: '+browserSupportFlag);
				handleNoGeoLocation(browserSupportFlag);
			
		    });
		  // Browser doesn't support Geolocation
		  } else {

			
				$(".loader-ajax-medium").fadeOut(function(){

					$('.message-box-text').fadeOut(function(){

						$('.message-box-text').html("Nous sommes désolé mais votre navigateur Internet ne nous permet pas de vous localiser.<br/>Vous pouvez mettre à jour votre navigateur pour bénéficier de cette fonctionnalité.").fadeIn(function(){
							$(this).oneTime('8s', function(){
								$('.message-box').fadeOut();
							})						
						});
					})
				});
									
		    browserSupportFlag = false;
			//Core.Map.DisplayMarkers(map,this.UserGeolocLatitude,this.UserGeolocLongitude);
		    handleNoGeolocation(browserSupportFlag);		
		  }

		  function handleNoGeolocation(errorFlag) {
			var paris = new google.maps.LatLng(48.856579, 2.351828);
		    if (errorFlag == true) {

				  Core.Map.UserGeolocLatitude = 48.856579;
				  Core.Map.UserGeolocLongitude = 2.351828;
					Core.MapValues.CenterLatitude = Core.Map.UserGeolocLatitude;
					Core.MapValues.CenterLongitude = Core.Map.UserGeolocLongitude;
		      		initialLocation = paris;
		
						$(".loader-ajax-medium").fadeOut(function(){

							$('.message-box-text').fadeOut(function(){

								$('.message-box-text').html("Nous n'avons pas pu vous localiser. Nous vous avons donc positionné à Paris.").fadeIn(function(){
									$(this).oneTime('8s', function(){
										$('.message-box').fadeOut();

									})						
								});


							})


						});
		
		    } else {
	      			initialLocation = paris;
			  		Core.Map.UserGeolocLatitude = 48.856579;
			  		Core.Map.UserGeolocLongitude = 2.351828;
					Core.MapValues.CenterLatitude = Core.Map.UserGeolocLatitude;
					Core.MapValues.CenterLongitude = Core.Map.UserGeolocLongitude;
		    }
			
			$('.click-relocate, .click-radio').attr('data' , "{longitude: '"+Core.Map.UserGeolocLatitude+"', latitude: '"+Core.Map.UserGeolocLongitude+"'}" );
			//Core.Map.DisplayMarkers(map,Core.Map.UserGeolocLatitude,Core.Map.UserGeolocLongitude);
			map.setZoom(12);
		    map.setCenter(initialLocation);

		  }
			
	},
	
	
	DisplayMarkers : function(mapSize,map,latitude, longitude, zoom){
			
			$('.click-relocate, .click-radio').attr('data' , "{longitude: '"+Core.MapValues.CenterLatitude+"', latitude: '"+Core.MapValues.CenterLongitude+"'}" );
		
			var searchfield = $('#sp-search-field').attr('value');
			var alt = $('#sp-search-field').attr('alt');
			if (searchfield == alt) {
				searchfield = '';
			}else{
				$('.search-cancel').css('display','inline');
			}
			
			var idartist_category = $('#idartist_category').attr('value');
			
			if (Core.Map.MarkersRequest != '') {
				Core.Map.MarkersRequest.abort();
			};
			
			$('.search-empty').css('display', 'none');
			
			Core.Map.MarkersRequest = 
			$.ajax({
			  url: '/sound/markers/',
			  type: 'POST',
			  dataType: 'xml',
				async : true,
			  data: {lat: Core.MapValues.CenterLatitude, lng : Core.MapValues.CenterLongitude, zoom : zoom, type: idartist_category, category : Core.MapValues.CurrentCategory, search : searchfield, iframe : Core.Map.iframe} ,
			  complete: function(xhr, textStatus) {
			    //called when complete
			  },
			  success: function(data, textStatus, xhr) {
			   
				$('.loader-ajax').hide();
				if ($(data).find('marker').length == 0) {
					
					$('.search-empty').fadeIn(function(){
						$(this).oneTime('4s', function(){
							$(this).fadeOut();
						})
					});
					
					
				}else{
					
						$(data).find('marker').each(function(){
						   var self = $(this);
						   var lng = self.attr('lng');
						   var lat = self.attr('lat');
						   var point = new google.maps.LatLng(lat,lng);
						   var type = self.attr('type');
						   var address = self.attr('address');
						   var id = self.attr('nr');
						   var index = self.attr('index');
						   var name = self.attr('name');
						   var html = self.attr('html');
						   var category = self.attr('category');
						   var categorybis = self.attr('categorybis');
						   var type = self.attr('type');
						   var pin_category = self.attr('pin_category');

						   Core.Map.CreateMarker(mapSize,map,point, name, html, category,categorybis,index, id,  pin_category,type);

						});
					
				}
			
				

					
					
					Core.Map.XmlMarkers = data;
					//	Default hide markers
					//	Core.Map.HideMarkers('scene');

			  },
			  error: function(xhr, textStatus, errorThrown) {
			    //called when there is an error
			  }
			});
			
		
			
		
			
	},
	CreateMarker : function(mapSize, map_instance, point, name, html, category, categorybis,index, id, pin_category, type){
		
	//	console.log(Core.Map.gmarkersSmallMap);
		
			  var shadow = new google.maps.MarkerImage('/img/front/soundplace/categorie/shadow.png',
		      // The shadow image is larger in the horizontal dimension
		      // while the position and offset are the same as for the main image.
		      new google.maps.Size(68, 26),
		      new google.maps.Point(0,0),
		      new google.maps.Point(64, 26));
		
		
			  var g = google.maps;
			  var marker = new g.Marker({ 'position': point, map: map_instance,
			    title: name,
				clickable: true,
				draggable: false,
			    icon: pin_category,
				shadow : shadow
			  });


			  // Store category, name, and id as marker properties
			  marker.category = category;
			  marker.categorybis = categorybis;
			  marker.type = type;
			  marker.name = name;
			  marker.id = id;
			
				if ($("#soundplace").length == 0 ) {
//					var map_css_selector = 'small';
					Core.Map.gmarkersSmallMap.push(marker);
				}else{
					Core.Map.gmarkersFullscreenMap.push(marker);
//					var map_css_selector = 'fullscreen';			
				}
			/*
				if ($('#sp-map-big').length > 0) {	
					Core.Map.gmarkersFullscreenMap.push(marker);
				}else{
					Core.Map.gmarkersSmallMap.push(marker);
				}
			*/

			  infoBubble = new InfoBubble({
				shadowStyle 	: 0, // 0,1,2
				padding			: 0,
				borderRadius	: 0,
				borderWidth		: 0,
				borderColor		: 'transparent',
				backgroundColor : 'transparent',
				minWidth		: 230,
				maxWidth		: 340,
				minHeight		: 120,
				maxHeight		: 144,
				arrowSize		: 15,
				arrowPosition	: 25,
				arrowStyle		: 0, // 0, 1, 2;
				hideCloseButton : true
			  });
			  
			// Remove loader
				$('.loader').remove();
					//console.log(this.MapObject);
					
			  g.event.addListener(marker, "click", function() {
					if (infoBubble.isOpen()) {
						infoBubble.close();				
					}
					Core.Map.StartRadioIndex = index;
					
					infoBubble.setContent(html);
				    infoBubble.open(map_instance, marker);
			  });
			
				
			

			/*
			  g.event.addListener(marker, "mouseover", function() {
					if (!infoBubble.isOpen()) {
						infoBubble.close(map, marker);				
					}

					infoBubble.setContent(html);
				    infoBubble.open(map, marker);
				
			  });
			*/

	},
	ShowMarkers: function(category){
		
		if ($('#sp-map-big').length > 0) {
		//	console.log('fullscreen filter')
			markersArray  =  Core.Map.gmarkersFullscreenMap;
		}else{
		//	console.log('small filter');
		//	console.log(Core.Map.gmarkersSmallMap);
			markersArray  =  Core.Map.gmarkersSmallMap;
		}
		
		  // Show all markers of one category
		  for(var i= 0, m; m = markersArray[i]; i++) {
	
		   if (m.category == category) {
		//	console.log('show '+m.categorybis+ "== "+category+' '+ m.category +'=='+ category);
		    m.setVisible(true);
		   }
		  }
			//console.log(category);
		 if (infoBubble.isOpen()) {
			infoBubble.close(this);
		}
		
		  for(var i= 0, m; m = markersArray[i]; i++) {
		   if (m.category != category ) {
			//	console.log("hide "+m.category +" != "+ category +" || "+ m.categorybis +" != "+category);
		    m.setVisible(false);
		   }
		  }
		
	},
	HideMarkers : function(category){
		if ($('#sp-map-big').length > 0) {
		//	console.log('fullscreen filter')
			markersArray  =  Core.Map.gmarkersFullscreenMap;
		}else{
		//	console.log('small filter');
		//	console.log(Core.Map.gmarkersSmallMap);
			markersArray  =  Core.Map.gmarkersSmallMap;
		}	
		  for(var i= 0, m; m = markersArray[i]; i++) {
		   if (m.category == category ) {
			//	console.log("hide "+m.category +" != "+ category +" || "+ m.categorybis +" != "+category);
		    m.setVisible(false);
		   }
		  }
		  // Clear the checkbox of a hidden category
		 // document.getElementById(category).checked = false;
		  //iw.close();
		
		if (infoBubble.isOpen()) {
			infoBubble.close(this);
		}
		
	},
	SortMarkers : function(selector,category){

		// Show all pins
	  if(category == ''){

		$links =  $(selector).parent().find('.static');		
		$.each($links, function(index, val) {
				var data =  $(val).metadata();
				 Core.Map.ShowMarkers( data.class_name);
		});
		
		
	  }else{			
		  Core.Map.ShowMarkers(category);
		  Core.Map.HideMarkers(category);
	   }
		
	},
	RemoveMarkers : function(){
		 var markersArray = [];
		if (markersArray) {
	      for (i in markersArray) {
	        markersArray[i].setMap(null);
	      }
	    }
		
	},
	InfoBubbleExpand : function(selector){
		
		$("#"+selector).animate({
		    width:'320px'  });
		//console.log(selector);
		
	},
	Search : function(map, gmarkers){
/*
			function trim(str)
			{
			    if(!str || typeof str != 'string')
			        return null;

			    return str.replace(/^[\s]+/,'').replace(/[\s]+$/,'').replace(/[\s]{2,}/,' ');
			}
			search_value =	$("#sp-search-field").val();
			
			//search_value = trim(search_value);
			 var strReplaceAll = search_value;
			 var intIndexOfMatch = strReplaceAll.indexOf( " " );
			  
			 // Loop over the string value replacing out each matching
			 // substring.
			 while (intIndexOfMatch != -1){
			 // Relace out the current instance.
			 strReplaceAll = strReplaceAll.replace( " ", "|" )
			  
			 // Get the index of any next matching substring.
			 intIndexOfMatch = strReplaceAll.indexOf( " " );
			}
			
			for(var i= 0, m; m = gmarkers[i]; i++) {

					name = m.name.toLowerCase();
					var matchPos1 = name.search(strReplaceAll.toLowerCase());
					if(matchPos1 != -1){
						m.setVisible(true);
						//console.log('found : '+name );
					}else{
						m.setVisible(false);
						//console.log('not found : '+name );
					}
				
			}
			*/
			
			map.setZoom(5);
			//var saint_armand_montrond = new google.maps.LatLng(46.950262, 1.73584);
	    	//map.setCenter(saint_armand_montrond);

			infoBubble.close(map);

			return false;



		
	},
	CloseInfo : function(index){
			$('#bulle-'+index).fadeOut();
			infoBubble.close(this.MapObject);	
	},
	Close : function(element){
		
		
		if (element == 'radio') {
			
			Core.Player.NextRadio = false;
			
		//	console.log('close radio');
			//	console.log('In progress'+Core.Map.Mp3InProgress);
			$("#sound-lightboxContent .artist-name").append('<div class="loader-ajax-medium"></div>');
			if (Core.Map.Mp3InProgress == true) {
				//thisMovie('MajesPlayer').toggle();
				//console.log("Toggle");
			}
			
				
					$("#content").css('display','block');
					$("#footer").css('display','block');
					$("#sound-lightboxOverlay").css('display','none');
					$("#sound-lightbox").fadeOut(function(){
	//					$("#sound-lightboxContent").html('');
						$("#soundplace").remove();
					});
				
			
			
		}else if( element == 'map' ){
				//console.log('In progress'+Core.Map.Mp3InProgress);
				$("#sound-lightboxContent #soundplace").append('<div class="loader-ajax-medium"></div>');
				if (Core.Map.Mp3InProgress == true) {
					//thisMovie('MajesPlayer').toggle();
					//console.log("Toggle");
				}
				
			
						$("#content").css('display','block');
						$("#footer").css('display','block');
						$("#sound-lightboxOverlay").css('display','none');
						$("#sound-lightbox").fadeOut(function(){

							$("#soundplace").remove();
						});
					//	delete tt.MapObject;
			
			
			
			
			
			
		}
		
		
		return false;
	},
	OpenRadio : function(element){

		if (element == 'map') {
			
				
				Core.Map.Mp3InProgress = false;
			
			//	$("#sound-lightboxOverlay").html('<div class="loader-ajax-medium"></div>').css('display','block');
				$('.loader-ajax-medium').css('display','inline');
				$("#sound-lightboxContent").load('/soundplace/carte',
				 function(){
					Core.Soundplace.Tooltip();
						$('.loader-ajax-medium').css('display','none');
						$('#sound-lightbox').css('display','block');
						$("#soundplace").css( {'width': $(window).width() , 'height': $(window).height() } );
						tt = Core.Map;
						tt.Initialize("sp-map-big");
						google.maps.event.trigger(tt.MapObject, "resize");

						$(window).resize(function() {
							$("#soundplace").css( {'width': $(window).width() , 'height': $(window).height() } );
							google.maps.event.trigger(tt.MapObject, "resize");
						});


				});
			
			
			
		};
			return false;
			
		
	},
	Link : function(href){



			//	var	data = $(this).metadata();


			$("#sound-lightboxContent #soundplace").append('<div class="loader-ajax-medium"></div>');
			if (Core.Map.Mp3InProgress == true) {
				//thisMovie('MajesPlayer').toggle();
				//console.log("Toggle");
			}
			$("#sound-lightboxOverlay").css('display','none');
			$("#content").css('display','block');
			$("#footer").css('display','block');
		
					$("#content").css('display','block');
					$("#footer").css('display','block');
					$("#sound-lightboxOverlay").css('display','none');
					$("#sound-lightbox").fadeOut(function(){
						
						$("#sound-lightboxContent").html('');	
						
						$.address.value(href);
						Core.Common.Ajax(href,'Core.Common.JscrollPane(),Core.Common.Header($(this))');
					});




		return false;
	},
	Fullscreen: function(selector){
			//Core.Map.Initialize("sp-map-big");
			//Core.Map.Initialize();
			
			idartist_category = $('#idartist_category').attr('value');
			
			$("#sound-lightboxContent").load($(selector).attr('href'),{category : Core.MapValues.CurrentCategory},
			 function(){
				Core.Soundplace.Tooltip();
				$("#sound-lightboxOverlay").css('display','inline');
					$("#content").css('display','none');
					$('#sound-lightbox').css('display','block');
					$("#soundplace").css( {'width': $(window).width() , 'height': $(window).height() } );
					var tt = Core.Map;
					tt.Initialize("sp-map-big");
					google.maps.event.trigger(tt.MapObject, "resize");
				
					$(window).resize(function() {
						
						$("#soundplace").css( {'width': $(window).width() , 'height': $(window).height() } );
						google.maps.event.trigger(tt.MapObject, "resize");
					});
					
			
			});
			return false;
		
	},
	Play : function(selector, url_mp3, artist, title, idmedia, url_details, booplay, duration){
	
		// Show player
	
		
	
		if ($(selector).hasClass('pause')) {

			thisMovie('MajesPlayer').toggle();
			Core.Map.Mp3InProgress = true;
			$(selector).toggleClass('pause');
			$('#header-container .player .play').toggleClass('pause');
		}else if ($(selector).hasClass('live')){

			thisMovie('MajesPlayer').toggle();
			$(selector).addClass('pause');
			$('#header-container .player .play').toggleClass('pause');
		}else{
			
			$('#header-container .player').slideDown(function(){
				Core.Player.Position();
			});
			
			Core.Player.addMp3(url_mp3, artist, title, idmedia, url_details, booplay, duration);
			Core.Map.Mp3InProgress = true;
			$(selector).addClass('live');
			
			$(selector).addClass('pause');
			$('#header-container .player .play').addClass('pause');
		}
	
	
	
		return false;
	}
}




$(document).ready(function() {
	
	Core.Common.Initialize();
	Core.Player.Position();
	Core.Auth.Initialize();
	Core.Artist.Initialize();
	Core.Member.Initialize();
	Core.Hall.Initialize();
	Core.Home.Initialize();
	Core.Blog.Initialize();
	Core.Review.Initialize();
	Core.Concert.Initialize();
	Core.Media.Initialize();
	Core.Soundplace.Initialize();
});








