/* http://keith-wood.name/countdown.html
   Countdown for jQuery v1.5.7.
   Written by Keith Wood (kbwood{at}iinet.com.au) January 2008.
   Dual licensed under the GPL (http://dev.jquery.com/browser/trunk/jquery/GPL-LICENSE.txt) and 
   MIT (http://dev.jquery.com/browser/trunk/jquery/MIT-LICENSE.txt) licenses. 
   Please attribute the author if you use it. */

/* Display a countdown timer.
   Attach it with options like:
   $('div selector').countdown(
       {until: new Date(2009, 1 - 1, 1, 0, 0, 0), onExpiry: happyNewYear}); */

(function($) { // Hide scope, no $ conflict

/* Countdown manager. */
function Countdown() {
	this.regional = []; // Available regional settings, indexed by language code
	this.regional[''] = { // Default regional settings
		// The display texts for the counters
		labels: ['Years', 'Months', 'Weeks', 'Days', 'Hours', 'Minutes', 'Seconds'],
		// The display texts for the counters if only one
		labels1: ['Year', 'Month', 'Week', 'Day', 'Hour', 'Minute', 'Second'],
		compactLabels: ['y', 'm', 'w', 'd'], // The compact texts for the counters
		timeSeparator: ':', // Separator for time periods
		isRTL: false // True for right-to-left languages, false for left-to-right
	};
	this._defaults = {
		until: null, // new Date(year, mth - 1, day, hr, min, sec) - date/time to count down to
			// or numeric for seconds offset, or string for unit offset(s):
			// 'Y' years, 'O' months, 'W' weeks, 'D' days, 'H' hours, 'M' minutes, 'S' seconds
		since: null, // new Date(year, mth - 1, day, hr, min, sec) - date/time to count up from
			// or numeric for seconds offset, or string for unit offset(s):
			// 'Y' years, 'O' months, 'W' weeks, 'D' days, 'H' hours, 'M' minutes, 'S' seconds
		timezone: null, // The timezone (hours or minutes from GMT) for the target times,
			// or null for client local
		serverSync: null, // A function to retrieve the current server time for synchronisation
		format: 'dHMS', // Format for display - upper case for always, lower case only if non-zero,
			// 'Y' years, 'O' months, 'W' weeks, 'D' days, 'H' hours, 'M' minutes, 'S' seconds
		layout: '', // Build your own layout for the countdown
		compact: false, // True to display in a compact format, false for an expanded one
		description: '', // The description displayed for the countdown
		expiryUrl: '', // A URL to load upon expiry, replacing the current page
		expiryText: '', // Text to display upon expiry, replacing the countdown
		alwaysExpire: false, // True to trigger onExpiry even if never counted down
		onExpiry: null, // Callback when the countdown expires -
			// receives no parameters and 'this' is the containing division
		onTick: null, // Callback when the countdown is updated -
			// receives int[7] being the breakdown by period (based on format)
			// and 'this' is the containing division
		tickInterval: 1 // Interval (seconds) between onTick callbacks
	};
	$.extend(this._defaults, this.regional['']);
	this._serverSyncs = [];
}

var PROP_NAME = 'countdown';

var Y = 0; // Years
var O = 1; // Months
var W = 2; // Weeks
var D = 3; // Days
var H = 4; // Hours
var M = 5; // Minutes
var S = 6; // Seconds

$.extend(Countdown.prototype, {
	/* Class name added to elements to indicate already configured with countdown. */
	markerClassName: 'hasCountdown',
	
	/* Shared timer for all countdowns. */
	_timer: setInterval(function() { $.countdown._updateTargets(); }, 980),
	/* List of currently active countdown targets. */
	_timerTargets: [],
	
	/* Override the default settings for all instances of the countdown widget.
	   @param  options  (object) the new settings to use as defaults */
	setDefaults: function(options) {
		this._resetExtraLabels(this._defaults, options);
		extendRemove(this._defaults, options || {});
	},

	/* Convert a date/time to UTC.
	   @param  tz     (number) the hour or minute offset from GMT, e.g. +9, -360
	   @param  year   (Date) the date/time in that timezone or
	                  (number) the year in that timezone
	   @param  month  (number, optional) the month (0 - 11) (omit if year is a Date)
	   @param  day    (number, optional) the day (omit if year is a Date)
	   @param  hours  (number, optional) the hour (omit if year is a Date)
	   @param  mins   (number, optional) the minute (omit if year is a Date)
	   @param  secs   (number, optional) the second (omit if year is a Date)
	   @param  ms     (number, optional) the millisecond (omit if year is a Date)
	   @return  (Date) the equivalent UTC date/time */
	UTCDate: function(tz, year, month, day, hours, mins, secs, ms) {
		if (typeof year == 'object' && year.constructor == Date) {
			ms = year.getMilliseconds();
			secs = year.getSeconds();
			mins = year.getMinutes();
			hours = year.getHours();
			day = year.getDate();
			month = year.getMonth();
			year = year.getFullYear();
		}
		var d = new Date();
		d.setUTCFullYear(year);
		d.setUTCDate(1);
		d.setUTCMonth(month || 0);
		d.setUTCDate(day || 1);
		d.setUTCHours(hours || 0);
		d.setUTCMinutes((mins || 0) - (Math.abs(tz) < 30 ? tz * 60 : tz));
		d.setUTCSeconds(secs || 0);
		d.setUTCMilliseconds(ms || 0);
		return d;
	},

	/* Convert a set of periods into seconds.
	   Averaged for months and years.
	   @param  periods  (number[7]) the periods per year/month/week/day/hour/minute/second
	   @return  (number) the corresponding number of seconds */
	periodsToSeconds: function(periods) {
		return periods[0] * 31557600 + periods[1] * 2629800 + periods[2] * 604800 +
			periods[3] * 86400 + periods[4] * 3600 + periods[5] * 60 + periods[6];
	},

	/* Retrieve one or more settings values.
	   @param  name  (string, optional) the name of the setting to retrieve
	                 or 'all' for all instance settings or omit for all default settings
	   @return  (any) the requested setting(s) */
	_settingsCountdown: function(target, name) {
		if (!name) {
			return $.countdown._defaults;
		}
		var inst = $.data(target, PROP_NAME);
		return (name == 'all' ? inst.options : inst.options[name]);
	},

	/* Attach the countdown widget to a div.
	   @param  target   (element) the containing division
	   @param  options  (object) the initial settings for the countdown */
	_attachCountdown: function(target, options) {
		var $target = $(target);
		if ($target.hasClass(this.markerClassName)) {
			return;
		}
		$target.addClass(this.markerClassName);
		var inst = {options: $.extend({}, options),
			_periods: [0, 0, 0, 0, 0, 0, 0]};
		$.data(target, PROP_NAME, inst);
		this._changeCountdown(target);
	},

	/* Add a target to the list of active ones.
	   @param  target  (element) the countdown target */
	_addTarget: function(target) {
		if (!this._hasTarget(target)) {
			this._timerTargets.push(target);
		}
	},

	/* See if a target is in the list of active ones.
	   @param  target  (element) the countdown target
	   @return  (boolean) true if present, false if not */
	_hasTarget: function(target) {
		return ($.inArray(target, this._timerTargets) > -1);
	},

	/* Remove a target from the list of active ones.
	   @param  target  (element) the countdown target */
	_removeTarget: function(target) {
		this._timerTargets = $.map(this._timerTargets,
			function(value) { return (value == target ? null : value); }); // delete entry
	},

	/* Update each active timer target. */
	_updateTargets: function() {
		for (var i = this._timerTargets.length - 1; i >= 0; i--) {
			this._updateCountdown(this._timerTargets[i]);
		}
	},

	/* Redisplay the countdown with an updated display.
	   @param  target  (jQuery) the containing division
	   @param  inst    (object) the current settings for this instance */
	_updateCountdown: function(target, inst) {
		var $target = $(target);
		inst = inst || $.data(target, PROP_NAME);
		if (!inst) {
			return;
		}
		$target.html(this._generateHTML(inst));
		$target[(this._get(inst, 'isRTL') ? 'add' : 'remove') + 'Class']('countdown_rtl');
		var onTick = this._get(inst, 'onTick');
		if (onTick) {
			var periods = inst._hold != 'lap' ? inst._periods :
				this._calculatePeriods(inst, inst._show, new Date());
			var tickInterval = this._get(inst, 'tickInterval');
			if (tickInterval == 1 || this.periodsToSeconds(periods) % tickInterval == 0) {
				onTick.apply(target, [periods]);
			}
		}
		var expired = inst._hold != 'pause' &&
			(inst._since ? inst._now.getTime() < inst._since.getTime() :
			inst._now.getTime() >= inst._until.getTime());
		if (expired && !inst._expiring) {
			inst._expiring = true;
			if (this._hasTarget(target) || this._get(inst, 'alwaysExpire')) {
				this._removeTarget(target);
				var onExpiry = this._get(inst, 'onExpiry');
				if (onExpiry) {
					onExpiry.apply(target, []);
				}
				var expiryText = this._get(inst, 'expiryText');
				if (expiryText) {
					var layout = this._get(inst, 'layout');
					inst.options.layout = expiryText;
					this._updateCountdown(target, inst);
					inst.options.layout = layout;
				}
				var expiryUrl = this._get(inst, 'expiryUrl');
				if (expiryUrl) {
					window.location = expiryUrl;
				}
			}
			inst._expiring = false;
		}
		else if (inst._hold == 'pause') {
			this._removeTarget(target);
		}
		$.data(target, PROP_NAME, inst);
	},

	/* Reconfigure the settings for a countdown div.
	   @param  target   (element) the containing division
	   @param  options  (object) the new settings for the countdown or
	                    (string) an individual property name
	   @param  value    (any) the individual property value
	                    (omit if options is an object) */
	_changeCountdown: function(target, options, value) {
		options = options || {};
		if (typeof options == 'string') {
			var name = options;
			options = {};
			options[name] = value;
		}
		var inst = $.data(target, PROP_NAME);
		if (inst) {
			this._resetExtraLabels(inst.options, options);
			extendRemove(inst.options, options);
			this._adjustSettings(target, inst);
			$.data(target, PROP_NAME, inst);
			var now = new Date();
			if ((inst._since && inst._since < now) ||
					(inst._until && inst._until > now)) {
				this._addTarget(target);
			}
			this._updateCountdown(target, inst);
		}
	},

	/* Reset any extra labelsn and compactLabelsn entries if changing labels.
	   @param  base     (object) the options to be updated
	   @param  options  (object) the new option values */
	_resetExtraLabels: function(base, options) {
		var changingLabels = false;
		for (var n in options) {
			if (n.match(/[Ll]abels/)) {
				changingLabels = true;
				break;
			}
		}
		if (changingLabels) {
			for (var n in base) { // Remove custom numbered labels
				if (n.match(/[Ll]abels[0-9]/)) {
					base[n] = null;
				}
			}
		}
	},
	
	/* Calculate interal settings for an instance.
	   @param  target  (element) the containing division
	   @param  inst    (object) the current settings for this instance */
	_adjustSettings: function(target, inst) {
		var now;
		var serverSync = this._get(inst, 'serverSync');
		var serverOffset = 0;
		var serverEntry = null;
		for (var i = 0; i < this._serverSyncs.length; i++) {
			if (this._serverSyncs[i][0] == serverSync) {
				serverEntry = this._serverSyncs[i][1];
				break;
			}
		}
		if (serverEntry != null) {
			serverOffset = (serverSync ? serverEntry : 0);
			now = new Date();
		}
		else {
			var serverResult = (serverSync ? serverSync.apply(target, []) : null);
			now = new Date();
			serverOffset = (serverResult ? now.getTime() - serverResult.getTime() : 0);
			this._serverSyncs.push([serverSync, serverOffset]);
		}
		var timezone = this._get(inst, 'timezone');
		timezone = (timezone == null ? -now.getTimezoneOffset() : timezone);
		inst._since = this._get(inst, 'since');
		if (inst._since != null) {
			inst._since = this.UTCDate(timezone, this._determineTime(inst._since, null));
			if (inst._since && serverOffset) {
				inst._since.setMilliseconds(inst._since.getMilliseconds() + serverOffset);
			}
		}
		inst._until = this.UTCDate(timezone, this._determineTime(this._get(inst, 'until'), now));
		if (serverOffset) {
			inst._until.setMilliseconds(inst._until.getMilliseconds() + serverOffset);
		}
		inst._show = this._determineShow(inst);
	},

	/* Remove the countdown widget from a div.
	   @param  target  (element) the containing division */
	_destroyCountdown: function(target) {
		var $target = $(target);
		if (!$target.hasClass(this.markerClassName)) {
			return;
		}
		this._removeTarget(target);
		$target.removeClass(this.markerClassName).empty();
		$.removeData(target, PROP_NAME);
	},

	/* Pause a countdown widget at the current time.
	   Stop it running but remember and display the current time.
	   @param  target  (element) the containing division */
	_pauseCountdown: function(target) {
		this._hold(target, 'pause');
	},

	/* Pause a countdown widget at the current time.
	   Stop the display but keep the countdown running.
	   @param  target  (element) the containing division */
	_lapCountdown: function(target) {
		this._hold(target, 'lap');
	},

	/* Resume a paused countdown widget.
	   @param  target  (element) the containing division */
	_resumeCountdown: function(target) {
		this._hold(target, null);
	},

	/* Pause or resume a countdown widget.
	   @param  target  (element) the containing division
	   @param  hold    (string) the new hold setting */
	_hold: function(target, hold) {
		var inst = $.data(target, PROP_NAME);
		if (inst) {
			if (inst._hold == 'pause' && !hold) {
				inst._periods = inst._savePeriods;
				var sign = (inst._since ? '-' : '+');
				inst[inst._since ? '_since' : '_until'] =
					this._determineTime(sign + inst._periods[0] + 'y' +
						sign + inst._periods[1] + 'o' + sign + inst._periods[2] + 'w' +
						sign + inst._periods[3] + 'd' + sign + inst._periods[4] + 'h' + 
						sign + inst._periods[5] + 'm' + sign + inst._periods[6] + 's');
				this._addTarget(target);
			}
			inst._hold = hold;
			inst._savePeriods = (hold == 'pause' ? inst._periods : null);
			$.data(target, PROP_NAME, inst);
			this._updateCountdown(target, inst);
		}
	},

	/* Return the current time periods.
	   @param  target  (element) the containing division
	   @return  (number[7]) the current periods for the countdown */
	_getTimesCountdown: function(target) {
		var inst = $.data(target, PROP_NAME);
		return (!inst ? null : (!inst._hold ? inst._periods :
			this._calculatePeriods(inst, inst._show, new Date())));
	},

	/* Get a setting value, defaulting if necessary.
	   @param  inst  (object) the current settings for this instance
	   @param  name  (string) the name of the required setting
	   @return  (any) the setting's value or a default if not overridden */
	_get: function(inst, name) {
		return (inst.options[name] != null ?
			inst.options[name] : $.countdown._defaults[name]);
	},

	/* A time may be specified as an exact value or a relative one.
	   @param  setting      (string or number or Date) - the date/time value
	                        as a relative or absolute value
	   @param  defaultTime  (Date) the date/time to use if no other is supplied
	   @return  (Date) the corresponding date/time */
	_determineTime: function(setting, defaultTime) {
		var offsetNumeric = function(offset) { // e.g. +300, -2
			var time = new Date();
			time.setTime(time.getTime() + offset * 1000);
			return time;
		};
		var offsetString = function(offset) { // e.g. '+2d', '-4w', '+3h +30m'
			offset = offset.toLowerCase();
			var time = new Date();
			var year = time.getFullYear();
			var month = time.getMonth();
			var day = time.getDate();
			var hour = time.getHours();
			var minute = time.getMinutes();
			var second = time.getSeconds();
			var pattern = /([+-]?[0-9]+)\s*(s|m|h|d|w|o|y)?/g;
			var matches = pattern.exec(offset);
			while (matches) {
				switch (matches[2] || 's') {
					case 's': second += parseInt(matches[1], 10); break;
					case 'm': minute += parseInt(matches[1], 10); break;
					case 'h': hour += parseInt(matches[1], 10); break;
					case 'd': day += parseInt(matches[1], 10); break;
					case 'w': day += parseInt(matches[1], 10) * 7; break;
					case 'o':
						month += parseInt(matches[1], 10); 
						day = Math.min(day, $.countdown._getDaysInMonth(year, month));
						break;
					case 'y':
						year += parseInt(matches[1], 10);
						day = Math.min(day, $.countdown._getDaysInMonth(year, month));
						break;
				}
				matches = pattern.exec(offset);
			}
			return new Date(year, month, day, hour, minute, second, 0);
		};
		var time = (setting == null ? defaultTime :
			(typeof setting == 'string' ? offsetString(setting) :
			(typeof setting == 'number' ? offsetNumeric(setting) : setting)));
		if (time) time.setMilliseconds(0);
		return time;
	},

	/* Determine the number of days in a month.
	   @param  year   (number) the year
	   @param  month  (number) the month
	   @return  (number) the days in that month */
	_getDaysInMonth: function(year, month) {
		return 32 - new Date(year, month, 32).getDate();
	},

	/* Generate the HTML to display the countdown widget.
	   @param  inst  (object) the current settings for this instance
	   @return  (string) the new HTML for the countdown display */
	_generateHTML: function(inst) {
		// Determine what to show
		inst._periods = periods = (inst._hold ? inst._periods :
			this._calculatePeriods(inst, inst._show, new Date()));
		// Show all 'asNeeded' after first non-zero value
		var shownNonZero = false;
		var showCount = 0;
		var show = $.extend({}, inst._show);
		for (var period = 0; period < inst._show.length; period++) {
			shownNonZero |= (inst._show[period] == '?' && periods[period] > 0);
			show[period] = (inst._show[period] == '?' && !shownNonZero ? null : inst._show[period]);
			showCount += (show[period] ? 1 : 0);
		}
		var compact = this._get(inst, 'compact');
		var layout = this._get(inst, 'layout');
		var labels = (compact ? this._get(inst, 'compactLabels') : this._get(inst, 'labels'));
		var timeSeparator = this._get(inst, 'timeSeparator');
		var description = this._get(inst, 'description') || '';
		var showCompact = function(period) {
			var labelsNum = $.countdown._get(inst, 'compactLabels' + periods[period]);
			return (show[period] ? periods[period] +
				(labelsNum ? labelsNum[period] : labels[period]) + ' ' : '');
		};
		var showFull = function(period) {
			var labelsNum = $.countdown._get(inst, 'labels' + periods[period]);
			return (show[period] ?
				'<span class="countdown_section"><span class="countdown_amount">' +
				periods[period] + '</span><br/>' +
				(labelsNum ? labelsNum[period] : labels[period]) + '</span>' : '');
		};
		return (layout ? this._buildLayout(inst, show, layout, compact) :
			((compact ? // Compact version
			'<span class="countdown_row countdown_amount' +
			(inst._hold ? ' countdown_holding' : '') + '">' + 
			showCompact(Y) + showCompact(O) + showCompact(W) + showCompact(D) + 
			(show[H] ? this._minDigits(periods[H], 2) : '') +
			(show[M] ? (show[H] ? timeSeparator : '') +
			this._minDigits(periods[M], 2) : '') +
			(show[S] ? (show[H] || show[M] ? timeSeparator : '') +
			this._minDigits(periods[S], 2) : '') :
			// Full version
			'<span class="countdown_row countdown_show' + showCount +
			(inst._hold ? ' countdown_holding' : '') + '">' +
			showFull(Y) + showFull(O) + showFull(W) + showFull(D) +
			showFull(H) + showFull(M) + showFull(S)) + '</span>' +
			(description ? '<span class="countdown_row countdown_descr">' + description + '</span>' : '')));
	},

	/* Construct a custom layout.
	   @param  inst     (object) the current settings for this instance
	   @param  show     (string[7]) flags indicating which periods are requested
	   @param  layout   (string) the customised layout
	   @param  compact  (boolean) true if using compact labels
	   @return  (string) the custom HTML */
	_buildLayout: function(inst, show, layout, compact) {
		var labels = this._get(inst, (compact ? 'compactLabels' : 'labels'));
		var labelFor = function(index) {
			return ($.countdown._get(inst,
				(compact ? 'compactLabels' : 'labels') + inst._periods[index]) ||
				labels)[index];
		};
		var digit = function(value, position) {
			return Math.floor(value / position) % 10;
		};
		var subs = {desc: this._get(inst, 'description'), sep: this._get(inst, 'timeSeparator'),
			yl: labelFor(Y), yn: inst._periods[Y], ynn: this._minDigits(inst._periods[Y], 2),
			ynnn: this._minDigits(inst._periods[Y], 3), y1: digit(inst._periods[Y], 1),
			y10: digit(inst._periods[Y], 10), y100: digit(inst._periods[Y], 100),
			y1000: digit(inst._periods[Y], 1000),
			ol: labelFor(O), on: inst._periods[O], onn: this._minDigits(inst._periods[O], 2),
			onnn: this._minDigits(inst._periods[O], 3), o1: digit(inst._periods[O], 1),
			o10: digit(inst._periods[O], 10), o100: digit(inst._periods[O], 100),
			o1000: digit(inst._periods[O], 1000),
			wl: labelFor(W), wn: inst._periods[W], wnn: this._minDigits(inst._periods[W], 2),
			wnnn: this._minDigits(inst._periods[W], 3), w1: digit(inst._periods[W], 1),
			w10: digit(inst._periods[W], 10), w100: digit(inst._periods[W], 100),
			w1000: digit(inst._periods[W], 1000),
			dl: labelFor(D), dn: inst._periods[D], dnn: this._minDigits(inst._periods[D], 2),
			dnnn: this._minDigits(inst._periods[D], 3), d1: digit(inst._periods[D], 1),
			d10: digit(inst._periods[D], 10), d100: digit(inst._periods[D], 100),
			d1000: digit(inst._periods[D], 1000),
			hl: labelFor(H), hn: inst._periods[H], hnn: this._minDigits(inst._periods[H], 2),
			hnnn: this._minDigits(inst._periods[H], 3), h1: digit(inst._periods[H], 1),
			h10: digit(inst._periods[H], 10), h100: digit(inst._periods[H], 100),
			h1000: digit(inst._periods[H], 1000),
			ml: labelFor(M), mn: inst._periods[M], mnn: this._minDigits(inst._periods[M], 2),
			mnnn: this._minDigits(inst._periods[M], 3), m1: digit(inst._periods[M], 1),
			m10: digit(inst._periods[M], 10), m100: digit(inst._periods[M], 100),
			m1000: digit(inst._periods[M], 1000),
			sl: labelFor(S), sn: inst._periods[S], snn: this._minDigits(inst._periods[S], 2),
			snnn: this._minDigits(inst._periods[S], 3), s1: digit(inst._periods[S], 1),
			s10: digit(inst._periods[S], 10), s100: digit(inst._periods[S], 100),
			s1000: digit(inst._periods[S], 1000)};
		var html = layout;
		// Replace period containers: {p<}...{p>}
		for (var i = 0; i < 7; i++) {
			var period = 'yowdhms'.charAt(i);
			var re = new RegExp('\\{' + period + '<\\}(.*)\\{' + period + '>\\}', 'g');
			html = html.replace(re, (show[i] ? '$1' : ''));
		}
		// Replace period values: {pn}
		$.each(subs, function(n, v) {
			var re = new RegExp('\\{' + n + '\\}', 'g');
			html = html.replace(re, v);
		});
		return html;
	},

	/* Ensure a numeric value has at least n digits for display.
	   @param  value  (number) the value to display
	   @param  len    (number) the minimum length
	   @return  (string) the display text */
	_minDigits: function(value, len) {
		value = '' + value;
		if (value.length >= len) {
			return value;
		}
		value = '0000000000' + value;
		return value.substr(value.length - len);
	},

	/* Translate the format into flags for each period.
	   @param  inst  (object) the current settings for this instance
	   @return  (string[7]) flags indicating which periods are requested (?) or
	            required (!) by year, month, week, day, hour, minute, second */
	_determineShow: function(inst) {
		var format = this._get(inst, 'format');
		var show = [];
		show[Y] = (format.match('y') ? '?' : (format.match('Y') ? '!' : null));
		show[O] = (format.match('o') ? '?' : (format.match('O') ? '!' : null));
		show[W] = (format.match('w') ? '?' : (format.match('W') ? '!' : null));
		show[D] = (format.match('d') ? '?' : (format.match('D') ? '!' : null));
		show[H] = (format.match('h') ? '?' : (format.match('H') ? '!' : null));
		show[M] = (format.match('m') ? '?' : (format.match('M') ? '!' : null));
		show[S] = (format.match('s') ? '?' : (format.match('S') ? '!' : null));
		return show;
	},
	
	/* Calculate the requested periods between now and the target time.
	   @param  inst  (object) the current settings for this instance
	   @param  show  (string[7]) flags indicating which periods are requested/required
	   @param  now   (Date) the current date and time
	   @return  (number[7]) the current time periods (always positive)
	            by year, month, week, day, hour, minute, second */
	_calculatePeriods: function(inst, show, now) {
		// Find endpoints
		inst._now = now;
		inst._now.setMilliseconds(0);
		var until = new Date(inst._now.getTime());
		if (inst._since) {
			if (now.getTime() < inst._since.getTime()) {
				inst._now = now = until;
			}
			else {
				now = inst._since;
			}
		}
		else {
			until.setTime(inst._until.getTime());
			if (now.getTime() > inst._until.getTime()) {
				inst._now = now = until;
			}
		}
		// Calculate differences by period
		var periods = [0, 0, 0, 0, 0, 0, 0];
		if (show[Y] || show[O]) {
			// Treat end of months as the same
			var lastNow = $.countdown._getDaysInMonth(now.getFullYear(), now.getMonth());
			var lastUntil = $.countdown._getDaysInMonth(until.getFullYear(), until.getMonth());
			var sameDay = (until.getDate() == now.getDate() ||
				(until.getDate() >= Math.min(lastNow, lastUntil) &&
				now.getDate() >= Math.min(lastNow, lastUntil)));
			var getSecs = function(date) {
				return (date.getHours() * 60 + date.getMinutes()) * 60 + date.getSeconds();
			};
			var months = Math.max(0,
				(until.getFullYear() - now.getFullYear()) * 12 + until.getMonth() - now.getMonth() +
				((until.getDate() < now.getDate() && !sameDay) ||
				(sameDay && getSecs(until) < getSecs(now)) ? -1 : 0));
			periods[Y] = (show[Y] ? Math.floor(months / 12) : 0);
			periods[O] = (show[O] ? months - periods[Y] * 12 : 0);
			// Adjust for months difference and end of month if necessary
			var adjustDate = function(date, offset, last) {
				var wasLastDay = (date.getDate() == last);
				var lastDay = $.countdown._getDaysInMonth(date.getFullYear() + offset * periods[Y],
					date.getMonth() + offset * periods[O]);
				if (date.getDate() > lastDay) {
					date.setDate(lastDay);
				}
				date.setFullYear(date.getFullYear() + offset * periods[Y]);
				date.setMonth(date.getMonth() + offset * periods[O]);
				if (wasLastDay) {
					date.setDate(lastDay);
				}
				return date;
			};
			if (inst._since) {
				until = adjustDate(until, -1, lastUntil);
			}
			else {
				now = adjustDate(new Date(now.getTime()), +1, lastNow);
			}
		}
		var diff = Math.floor((until.getTime() - now.getTime()) / 1000);
		var extractPeriod = function(period, numSecs) {
			periods[period] = (show[period] ? Math.floor(diff / numSecs) : 0);
			diff -= periods[period] * numSecs;
		};
		extractPeriod(W, 604800);
		extractPeriod(D, 86400);
		extractPeriod(H, 3600);
		extractPeriod(M, 60);
		extractPeriod(S, 1);
		if (diff > 0 && !inst._since) { // Round up if left overs
			var multiplier = [1, 12, 4.3482, 7, 24, 60, 60];
			var lastShown = S;
			var max = 1;
			for (var period = S; period >= Y; period--) {
				if (show[period]) {
					if (periods[lastShown] >= max) {
						periods[lastShown] = 0;
						diff = 1;
					}
					if (diff > 0) {
						periods[period]++;
						diff = 0;
						lastShown = period;
						max = 1;
					}
				}
				max *= multiplier[period];
			}
		}
		return periods;
	}
});

/* jQuery extend now ignores nulls!
   @param  target  (object) the object to update
   @param  props   (object) the new settings
   @return  (object) the updated object */
function extendRemove(target, props) {
	$.extend(target, props);
	for (var name in props) {
		if (props[name] == null) {
			target[name] = null;
		}
	}
	return target;
}

/* Process the countdown functionality for a jQuery selection.
   @param  command  (string) the command to run (optional, default 'attach')
   @param  options  (object) the new settings to use for these countdown instances
   @return  (jQuery) for chaining further calls */
$.fn.countdown = function(options) {
	var otherArgs = Array.prototype.slice.call(arguments, 1);
	if (options == 'getTimes' || options == 'settings') {
		return $.countdown['_' + options + 'Countdown'].
			apply($.countdown, [this[0]].concat(otherArgs));
	}
	return this.each(function() {
		if (typeof options == 'string') {
			$.countdown['_' + options + 'Countdown'].apply($.countdown, [this].concat(otherArgs));
		}
		else {
			$.countdown._attachCountdown(this, options);
		}
	});
};

/* Initialise the countdown functionality. */
$.countdown = new Countdown(); // singleton instance

})(jQuery);



/*!
 * jCarousel - Riding carousels with jQuery
 *   http://sorgalla.com/jcarousel/
 *
 * Copyright (c) 2006 Jan Sorgalla (http://sorgalla.com)
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 *
 * Built on top of the jQuery library
 *   http://jquery.com
 *
 * Inspired by the "Carousel Component" by Bill Scott
 *   http://billwscott.com/carousel/
 */

(function(i){var q={vertical:false,rtl:false,start:1,offset:1,size:null,scroll:3,visible:null,animation:"normal",easing:"swing",auto:0,wrap:null,initCallback:null,reloadCallback:null,itemLoadCallback:null,itemFirstInCallback:null,itemFirstOutCallback:null,itemLastInCallback:null,itemLastOutCallback:null,itemVisibleInCallback:null,itemVisibleOutCallback:null,buttonNextHTML:"<div></div>",buttonPrevHTML:"<div></div>",buttonNextEvent:"click",buttonPrevEvent:"click",buttonNextCallback:null,buttonPrevCallback:null, itemFallbackDimension:null},r=false;i(window).bind("load.jcarousel",function(){r=true});i.jcarousel=function(a,c){this.options=i.extend({},q,c||{});this.autoStopped=this.locked=false;this.buttonPrevState=this.buttonNextState=this.buttonPrev=this.buttonNext=this.list=this.clip=this.container=null;if(!c||c.rtl===undefined)this.options.rtl=(i(a).attr("dir")||i("html").attr("dir")||"").toLowerCase()=="rtl";this.wh=!this.options.vertical?"width":"height";this.lt=!this.options.vertical?this.options.rtl? "right":"left":"top";for(var b="",d=a.className.split(" "),f=0;f<d.length;f++)if(d[f].indexOf("jcarousel-skin")!=-1){i(a).removeClass(d[f]);b=d[f];break}if(a.nodeName.toUpperCase()=="UL"||a.nodeName.toUpperCase()=="OL"){this.list=i(a);this.container=this.list.parent();if(this.container.hasClass("jcarousel-clip")){if(!this.container.parent().hasClass("jcarousel-container"))this.container=this.container.wrap("<div></div>");this.container=this.container.parent()}else if(!this.container.hasClass("jcarousel-container"))this.container= this.list.wrap("<div></div>").parent()}else{this.container=i(a);this.list=this.container.find("ul,ol").eq(0)}b!==""&&this.container.parent()[0].className.indexOf("jcarousel-skin")==-1&&this.container.wrap('<div class=" '+b+'"></div>');this.clip=this.list.parent();if(!this.clip.length||!this.clip.hasClass("jcarousel-clip"))this.clip=this.list.wrap("<div></div>").parent();this.buttonNext=i(".jcarousel-next",this.container);if(this.buttonNext.size()===0&&this.options.buttonNextHTML!==null)this.buttonNext= this.clip.after(this.options.buttonNextHTML).next();this.buttonNext.addClass(this.className("jcarousel-next"));this.buttonPrev=i(".jcarousel-prev",this.container);if(this.buttonPrev.size()===0&&this.options.buttonPrevHTML!==null)this.buttonPrev=this.clip.after(this.options.buttonPrevHTML).next();this.buttonPrev.addClass(this.className("jcarousel-prev"));this.clip.addClass(this.className("jcarousel-clip")).css({overflow:"hidden",position:"relative"});this.list.addClass(this.className("jcarousel-list")).css({overflow:"hidden", position:"relative",top:0,margin:0,padding:0}).css(this.options.rtl?"right":"left",0);this.container.addClass(this.className("jcarousel-container")).css({position:"relative"});!this.options.vertical&&this.options.rtl&&this.container.addClass("jcarousel-direction-rtl").attr("dir","rtl");var j=this.options.visible!==null?Math.ceil(this.clipping()/this.options.visible):null;b=this.list.children("li");var e=this;if(b.size()>0){var g=0,k=this.options.offset;b.each(function(){e.format(this,k++);g+=e.dimension(this, j)});this.list.css(this.wh,g+100+"px");if(!c||c.size===undefined)this.options.size=b.size()}this.container.css("display","block");this.buttonNext.css("display","block");this.buttonPrev.css("display","block");this.funcNext=function(){e.next()};this.funcPrev=function(){e.prev()};this.funcResize=function(){e.reload()};this.options.initCallback!==null&&this.options.initCallback(this,"init");if(!r&&i.browser.safari){this.buttons(false,false);i(window).bind("load.jcarousel",function(){e.setup()})}else this.setup()}; var h=i.jcarousel;h.fn=h.prototype={jcarousel:"0.2.7"};h.fn.extend=h.extend=i.extend;h.fn.extend({setup:function(){this.prevLast=this.prevFirst=this.last=this.first=null;this.animating=false;this.tail=this.timer=null;this.inTail=false;if(!this.locked){this.list.css(this.lt,this.pos(this.options.offset)+"px");var a=this.pos(this.options.start,true);this.prevFirst=this.prevLast=null;this.animate(a,false);i(window).unbind("resize.jcarousel",this.funcResize).bind("resize.jcarousel",this.funcResize)}}, reset:function(){this.list.empty();this.list.css(this.lt,"0px");this.list.css(this.wh,"10px");this.options.initCallback!==null&&this.options.initCallback(this,"reset");this.setup()},reload:function(){this.tail!==null&&this.inTail&&this.list.css(this.lt,h.intval(this.list.css(this.lt))+this.tail);this.tail=null;this.inTail=false;this.options.reloadCallback!==null&&this.options.reloadCallback(this);if(this.options.visible!==null){var a=this,c=Math.ceil(this.clipping()/this.options.visible),b=0,d=0; this.list.children("li").each(function(f){b+=a.dimension(this,c);if(f+1<a.first)d=b});this.list.css(this.wh,b+"px");this.list.css(this.lt,-d+"px")}this.scroll(this.first,false)},lock:function(){this.locked=true;this.buttons()},unlock:function(){this.locked=false;this.buttons()},size:function(a){if(a!==undefined){this.options.size=a;this.locked||this.buttons()}return this.options.size},has:function(a,c){if(c===undefined||!c)c=a;if(this.options.size!==null&&c>this.options.size)c=this.options.size;for(var b= a;b<=c;b++){var d=this.get(b);if(!d.length||d.hasClass("jcarousel-item-placeholder"))return false}return true},get:function(a){return i(".jcarousel-item-"+a,this.list)},add:function(a,c){var b=this.get(a),d=0,f=i(c);if(b.length===0){var j,e=h.intval(a);for(b=this.create(a);;){j=this.get(--e);if(e<=0||j.length){e<=0?this.list.prepend(b):j.after(b);break}}}else d=this.dimension(b);if(f.get(0).nodeName.toUpperCase()=="LI"){b.replaceWith(f);b=f}else b.empty().append(c);this.format(b.removeClass(this.className("jcarousel-item-placeholder")), a);f=this.options.visible!==null?Math.ceil(this.clipping()/this.options.visible):null;d=this.dimension(b,f)-d;a>0&&a<this.first&&this.list.css(this.lt,h.intval(this.list.css(this.lt))-d+"px");this.list.css(this.wh,h.intval(this.list.css(this.wh))+d+"px");return b},remove:function(a){var c=this.get(a);if(!(!c.length||a>=this.first&&a<=this.last)){var b=this.dimension(c);a<this.first&&this.list.css(this.lt,h.intval(this.list.css(this.lt))+b+"px");c.remove();this.list.css(this.wh,h.intval(this.list.css(this.wh))- b+"px")}},next:function(){this.tail!==null&&!this.inTail?this.scrollTail(false):this.scroll((this.options.wrap=="both"||this.options.wrap=="last")&&this.options.size!==null&&this.last==this.options.size?1:this.first+this.options.scroll)},prev:function(){this.tail!==null&&this.inTail?this.scrollTail(true):this.scroll((this.options.wrap=="both"||this.options.wrap=="first")&&this.options.size!==null&&this.first==1?this.options.size:this.first-this.options.scroll)},scrollTail:function(a){if(!(this.locked|| this.animating||!this.tail)){this.pauseAuto();var c=h.intval(this.list.css(this.lt));c=!a?c-this.tail:c+this.tail;this.inTail=!a;this.prevFirst=this.first;this.prevLast=this.last;this.animate(c)}},scroll:function(a,c){if(!(this.locked||this.animating)){this.pauseAuto();this.animate(this.pos(a),c)}},pos:function(a,c){var b=h.intval(this.list.css(this.lt));if(this.locked||this.animating)return b;if(this.options.wrap!="circular")a=a<1?1:this.options.size&&a>this.options.size?this.options.size:a;for(var d= this.first>a,f=this.options.wrap!="circular"&&this.first<=1?1:this.first,j=d?this.get(f):this.get(this.last),e=d?f:f-1,g=null,k=0,l=false,m=0;d?--e>=a:++e<a;){g=this.get(e);l=!g.length;if(g.length===0){g=this.create(e).addClass(this.className("jcarousel-item-placeholder"));j[d?"before":"after"](g);if(this.first!==null&&this.options.wrap=="circular"&&this.options.size!==null&&(e<=0||e>this.options.size)){j=this.get(this.index(e));if(j.length)g=this.add(e,j.clone(true))}}j=g;m=this.dimension(g);if(l)k+= m;if(this.first!==null&&(this.options.wrap=="circular"||e>=1&&(this.options.size===null||e<=this.options.size)))b=d?b+m:b-m}f=this.clipping();var p=[],o=0,n=0;j=this.get(a-1);for(e=a;++o;){g=this.get(e);l=!g.length;if(g.length===0){g=this.create(e).addClass(this.className("jcarousel-item-placeholder"));j.length===0?this.list.prepend(g):j[d?"before":"after"](g);if(this.first!==null&&this.options.wrap=="circular"&&this.options.size!==null&&(e<=0||e>this.options.size)){j=this.get(this.index(e));if(j.length)g= this.add(e,j.clone(true))}}j=g;m=this.dimension(g);if(m===0)throw Error("jCarousel: No width/height set for items. This will cause an infinite loop. Aborting...");if(this.options.wrap!="circular"&&this.options.size!==null&&e>this.options.size)p.push(g);else if(l)k+=m;n+=m;if(n>=f)break;e++}for(g=0;g<p.length;g++)p[g].remove();if(k>0){this.list.css(this.wh,this.dimension(this.list)+k+"px");if(d){b-=k;this.list.css(this.lt,h.intval(this.list.css(this.lt))-k+"px")}}k=a+o-1;if(this.options.wrap!="circular"&& this.options.size&&k>this.options.size)k=this.options.size;if(e>k){o=0;e=k;for(n=0;++o;){g=this.get(e--);if(!g.length)break;n+=this.dimension(g);if(n>=f)break}}e=k-o+1;if(this.options.wrap!="circular"&&e<1)e=1;if(this.inTail&&d){b+=this.tail;this.inTail=false}this.tail=null;if(this.options.wrap!="circular"&&k==this.options.size&&k-o+1>=1){d=h.margin(this.get(k),!this.options.vertical?"marginRight":"marginBottom");if(n-d>f)this.tail=n-f-d}if(c&&a===this.options.size&&this.tail){b-=this.tail;this.inTail= true}for(;a-- >e;)b+=this.dimension(this.get(a));this.prevFirst=this.first;this.prevLast=this.last;this.first=e;this.last=k;return b},animate:function(a,c){if(!(this.locked||this.animating)){this.animating=true;var b=this,d=function(){b.animating=false;a===0&&b.list.css(b.lt,0);if(!b.autoStopped&&(b.options.wrap=="circular"||b.options.wrap=="both"||b.options.wrap=="last"||b.options.size===null||b.last<b.options.size||b.last==b.options.size&&b.tail!==null&&!b.inTail))b.startAuto();b.buttons();b.notify("onAfterAnimation"); if(b.options.wrap=="circular"&&b.options.size!==null)for(var f=b.prevFirst;f<=b.prevLast;f++)if(f!==null&&!(f>=b.first&&f<=b.last)&&(f<1||f>b.options.size))b.remove(f)};this.notify("onBeforeAnimation");if(!this.options.animation||c===false){this.list.css(this.lt,a+"px");d()}else this.list.animate(!this.options.vertical?this.options.rtl?{right:a}:{left:a}:{top:a},this.options.animation,this.options.easing,d)}},startAuto:function(a){if(a!==undefined)this.options.auto=a;if(this.options.auto===0)return this.stopAuto(); if(this.timer===null){this.autoStopped=false;var c=this;this.timer=window.setTimeout(function(){c.next()},this.options.auto*1E3)}},stopAuto:function(){this.pauseAuto();this.autoStopped=true},pauseAuto:function(){if(this.timer!==null){window.clearTimeout(this.timer);this.timer=null}},buttons:function(a,c){if(a==null){a=!this.locked&&this.options.size!==0&&(this.options.wrap&&this.options.wrap!="first"||this.options.size===null||this.last<this.options.size);if(!this.locked&&(!this.options.wrap||this.options.wrap== "first")&&this.options.size!==null&&this.last>=this.options.size)a=this.tail!==null&&!this.inTail}if(c==null){c=!this.locked&&this.options.size!==0&&(this.options.wrap&&this.options.wrap!="last"||this.first>1);if(!this.locked&&(!this.options.wrap||this.options.wrap=="last")&&this.options.size!==null&&this.first==1)c=this.tail!==null&&this.inTail}var b=this;if(this.buttonNext.size()>0){this.buttonNext.unbind(this.options.buttonNextEvent+".jcarousel",this.funcNext);a&&this.buttonNext.bind(this.options.buttonNextEvent+ ".jcarousel",this.funcNext);this.buttonNext[a?"removeClass":"addClass"](this.className("jcarousel-next-disabled")).attr("disabled",a?false:true);this.options.buttonNextCallback!==null&&this.buttonNext.data("jcarouselstate")!=a&&this.buttonNext.each(function(){b.options.buttonNextCallback(b,this,a)}).data("jcarouselstate",a)}else this.options.buttonNextCallback!==null&&this.buttonNextState!=a&&this.options.buttonNextCallback(b,null,a);if(this.buttonPrev.size()>0){this.buttonPrev.unbind(this.options.buttonPrevEvent+ ".jcarousel",this.funcPrev);c&&this.buttonPrev.bind(this.options.buttonPrevEvent+".jcarousel",this.funcPrev);this.buttonPrev[c?"removeClass":"addClass"](this.className("jcarousel-prev-disabled")).attr("disabled",c?false:true);this.options.buttonPrevCallback!==null&&this.buttonPrev.data("jcarouselstate")!=c&&this.buttonPrev.each(function(){b.options.buttonPrevCallback(b,this,c)}).data("jcarouselstate",c)}else this.options.buttonPrevCallback!==null&&this.buttonPrevState!=c&&this.options.buttonPrevCallback(b, null,c);this.buttonNextState=a;this.buttonPrevState=c},notify:function(a){var c=this.prevFirst===null?"init":this.prevFirst<this.first?"next":"prev";this.callback("itemLoadCallback",a,c);if(this.prevFirst!==this.first){this.callback("itemFirstInCallback",a,c,this.first);this.callback("itemFirstOutCallback",a,c,this.prevFirst)}if(this.prevLast!==this.last){this.callback("itemLastInCallback",a,c,this.last);this.callback("itemLastOutCallback",a,c,this.prevLast)}this.callback("itemVisibleInCallback", a,c,this.first,this.last,this.prevFirst,this.prevLast);this.callback("itemVisibleOutCallback",a,c,this.prevFirst,this.prevLast,this.first,this.last)},callback:function(a,c,b,d,f,j,e){if(!(this.options[a]==null||typeof this.options[a]!="object"&&c!="onAfterAnimation")){var g=typeof this.options[a]=="object"?this.options[a][c]:this.options[a];if(i.isFunction(g)){var k=this;if(d===undefined)g(k,b,c);else if(f===undefined)this.get(d).each(function(){g(k,this,d,b,c)});else{a=function(m){k.get(m).each(function(){g(k, this,m,b,c)})};for(var l=d;l<=f;l++)l!==null&&!(l>=j&&l<=e)&&a(l)}}}},create:function(a){return this.format("<li></li>",a)},format:function(a,c){a=i(a);for(var b=a.get(0).className.split(" "),d=0;d<b.length;d++)b[d].indexOf("jcarousel-")!=-1&&a.removeClass(b[d]);a.addClass(this.className("jcarousel-item")).addClass(this.className("jcarousel-item-"+c)).css({"float":this.options.rtl?"right":"left","list-style":"none"}).attr("jcarouselindex",c);return a},className:function(a){return a+" "+a+(!this.options.vertical? "-horizontal":"-vertical")},dimension:function(a,c){var b=a.jquery!==undefined?a[0]:a,d=!this.options.vertical?(b.offsetWidth||h.intval(this.options.itemFallbackDimension))+h.margin(b,"marginLeft")+h.margin(b,"marginRight"):(b.offsetHeight||h.intval(this.options.itemFallbackDimension))+h.margin(b,"marginTop")+h.margin(b,"marginBottom");if(c==null||d==c)return d;d=!this.options.vertical?c-h.margin(b,"marginLeft")-h.margin(b,"marginRight"):c-h.margin(b,"marginTop")-h.margin(b,"marginBottom");i(b).css(this.wh, d+"px");return this.dimension(b)},clipping:function(){return!this.options.vertical?this.clip[0].offsetWidth-h.intval(this.clip.css("borderLeftWidth"))-h.intval(this.clip.css("borderRightWidth")):this.clip[0].offsetHeight-h.intval(this.clip.css("borderTopWidth"))-h.intval(this.clip.css("borderBottomWidth"))},index:function(a,c){if(c==null)c=this.options.size;return Math.round(((a-1)/c-Math.floor((a-1)/c))*c)+1}});h.extend({defaults:function(a){return i.extend(q,a||{})},margin:function(a,c){if(!a)return 0; var b=a.jquery!==undefined?a[0]:a;if(c=="marginRight"&&i.browser.safari){var d={display:"block","float":"none",width:"auto"},f,j;i.swap(b,d,function(){f=b.offsetWidth});d.marginRight=0;i.swap(b,d,function(){j=b.offsetWidth});return j-f}return h.intval(i.css(b,c))},intval:function(a){a=parseInt(a,10);return isNaN(a)?0:a}});i.fn.jcarousel=function(a){if(typeof a=="string"){var c=i(this).data("jcarousel"),b=Array.prototype.slice.call(arguments,1);return c[a].apply(c,b)}else return this.each(function(){i(this).data("jcarousel", new h(this,a))})}})(jQuery);


/*
 * --------------------------------------------------------------------
 * jQuery-Plugin - selectToUISlider - creates a UI slider component from a select element(s)
 * by Scott Jehl, scott@filamentgroup.com
 * http://www.filamentgroup.com
 * reference article: http://www.filamentgroup.com/lab/update_jquery_ui_16_slider_from_a_select_element/
 * demo page: http://www.filamentgroup.com/examples/slider_v2/index.html
 *
 * Copyright (c) 2008 Filament Group, Inc
 * Dual licensed under the MIT (filamentgroup.com/examples/mit-license.txt) and GPL (filamentgroup.com/examples/gpl-license.txt) licenses.
 *
 * Usage Notes: please refer to our article above for documentation
 *
 * --------------------------------------------------------------------
 */


jQuery.fn.selectToUISlider = function(settings){
        var selects = jQuery(this);

        //accessible slider options
        var options = jQuery.extend({
                labels: 3, //number of visible labels
                tooltip: true, //show tooltips, boolean
                tooltipSrc: 'text',//accepts 'value' as well
                labelSrc: 'value',//accepts 'value' as well        ,
                sliderOptions: null
        }, settings);


        //handle ID attrs - selects each need IDs for handles to find them
        var handleIds = (function(){
                var tempArr = [];
                selects.each(function(){
                        tempArr.push('handle_'+jQuery(this).attr('id'));
                });
                return tempArr;
        })();

        //array of all option elements in select element (ignores optgroups)
        var selectOptions = (function(){
                var opts = [];
                selects.eq(0).find('option').each(function(){
                        opts.push({
                                value: jQuery(this).attr('value'),
                                text: jQuery(this).text()
                        });
                });
                return opts;
        })();

        //array of opt groups if present
        var groups = (function(){
                if(selects.eq(0).find('optgroup').size()>0){
                        var groupedData = [];
                        selects.eq(0).find('optgroup').each(function(i){
                                groupedData[i] = {};
                                groupedData[i].label = jQuery(this).attr('label');
                                groupedData[i].options = [];
                                jQuery(this).find('option').each(function(){
                                        groupedData[i].options.push({text: jQuery(this).text(), value: jQuery(this).attr('value')});
                                });
                        });
                        return groupedData;
                }
                else return null;
        })();

        //check if obj is array
        function isArray(obj) {
                return obj.constructor == Array;
        }
        //return tooltip text from option index
        function ttText(optIndex){
                return (options.tooltipSrc == 'text') ? selectOptions[optIndex].text : selectOptions[optIndex].value;
        }

        //plugin-generated slider options (can be overridden)
        var sliderOptions = {
                step: 1,
                min: 0,
                orientation: 'horizontal',
                max: selectOptions.length-1,
                range: selects.length > 1,//multiple select elements = true
                slide: function(e, ui) {//slide function
                                var thisHandle = jQuery(ui.handle);
                                //handle feedback
                                var textval = ttText(ui.value);
                                thisHandle
                                        .attr('aria-valuetext', textval)
                                        .attr('aria-valuenow', ui.value)
                                        .find('.ui-slider-tooltip .ttContent')
                                                .text( textval );

                                //control original select menu
                                var currSelect = jQuery('#' + thisHandle.attr('id').split('handle_')[1]);
                                currSelect.find('option').eq(ui.value).attr('selected', 'selected');
                },
                values: (function(){
                        var values = [];
                        selects.each(function(){
                                values.push( jQuery(this).get(0).selectedIndex );
                        });
                        return values;
                })()
        };

        //slider options from settings
        options.sliderOptions = (settings) ? jQuery.extend(sliderOptions, settings.sliderOptions) : sliderOptions;

        //select element change event
        selects.bind('change keyup click', function(){
                var thisIndex = jQuery(this).get(0).selectedIndex;
                var thisHandle = jQuery('#handle_'+ jQuery(this).attr('id'));
                var handleIndex = thisHandle.data('handleNum');
                thisHandle.parents('.ui-slider:eq(0)').slider("values", handleIndex, thisIndex);
        });


        //create slider component div
        var sliderComponent = jQuery('<div></div>');

        //CREATE HANDLES
        selects.each(function(i){
                var hidett = '';

                //associate label for ARIA
                var thisLabel = jQuery('label[for=' + jQuery(this).attr('id') +']');
                //labelled by aria doesn't seem to work on slider handle. Using title attr as backup
                var labelText = (thisLabel.size()>0) ? 'Slider control for '+ thisLabel.text()+'' : '';
                var thisLabelId = thisLabel.attr('id') || thisLabel.attr('id', 'label_'+handleIds[i]).attr('id');


                if( options.tooltip == false ){hidett = ' style="display: none;"';}
                jQuery('<a '+
                                'href="#" tabindex="0" '+
                                'id="'+handleIds[i]+'" '+
                                'class="ui-slider-handle" '+
                                'role="slider" '+
                                'aria-labelledby="'+thisLabelId+'" '+
                                'aria-valuemin="'+options.sliderOptions.min+'" '+
                                'aria-valuemax="'+options.sliderOptions.max+'" '+
                                'aria-valuenow="'+options.sliderOptions.values[i]+'" '+
                                'aria-valuetext="'+ttText(options.sliderOptions.values[i])+'" '+
                        '><span class="screenReaderContext">'+labelText+'</span>'+
                        '<span class="ui-slider-tooltip ui-widget-content ui-corner-all"'+ hidett +'><span class="ttContent"></span>'+
                                '<span class="ui-tooltip-pointer-down ui-widget-content"><span class="ui-tooltip-pointer-down-inner"></span></span>'+
                        '</span></a>')
                        .data('handleNum',i)
                        .appendTo(sliderComponent);
        });

        //CREATE SCALE AND TICS

        //write dl if there are optgroups
        if(groups) {
                var inc = 0;
                var scale = sliderComponent.append('<dl class="ui-slider-scale ui-helper-reset" role="presentation"></dl>').find('.ui-slider-scale:eq(0)');
                jQuery(groups).each(function(h){
                        scale.append('<dt style="width: '+ (100/groups.length).toFixed(2) +'%' +'; left:'+ (h/(groups.length-1) * 100).toFixed(2)  +'%' +'"><span>'+this.label+'</span></dt>');//class name becomes camelCased label
                        var groupOpts = this.options;
                        jQuery(this.options).each(function(i){
                                var style = (inc == selectOptions.length-1 || inc == 0) ? 'style="display: none;"' : '' ;
                                var labelText = (options.labelSrc == 'text') ? groupOpts[i].text : groupOpts[i].value;
                                scale.append('<dd style="left:'+ leftVal(inc) +'"><span class="ui-slider-label">'+ labelText +'</span><span class="ui-slider-tic ui-widget-content"'+ style +'></span></dd>');
                                inc++;
                        });
                });
        }
        //write ol
        else {
                var scale = sliderComponent.append('<ol class="ui-slider-scale ui-helper-reset" role="presentation"></ol>').find('.ui-slider-scale:eq(0)');
                jQuery(selectOptions).each(function(i){
                        var style = (i == selectOptions.length-1 || i == 0) ? '' : '' ;
                        var labelText = (options.labelSrc == 'text') ? this.text : this.value;
                        scale.append('<li style="left:'+ leftVal(i) +'"><span class="ui-slider-label">'+ labelText +'</span><span class="ui-slider-tic ui-widget-content"'+ style +'></span></li>');
                });
        }

        function leftVal(i){
                return (i/(selectOptions.length-1) * 100).toFixed(2)  +'%';

        }




        //show and hide labels depending on labels pref
        //show the last one if there are more than 1 specified
        if(options.labels > 1) sliderComponent.find('.ui-slider-scale li:last span.ui-slider-label, .ui-slider-scale dd:last span.ui-slider-label').addClass('ui-slider-label-show');

        //set increment
        var increm = Math.max(1, Math.round(selectOptions.length / options.labels));
        //show em based on inc
        for(var j=0; j<selectOptions.length; j+=increm){
                if((selectOptions.length - j) > increm){//don't show if it's too close to the end label
                        sliderComponent.find('.ui-slider-scale li:eq('+ j +') span.ui-slider-label, .ui-slider-scale dd:eq('+ j +') span.ui-slider-label').addClass('ui-slider-label-show');
                }
        }

        //style the dt's
        sliderComponent.find('.ui-slider-scale dt').each(function(i){
                jQuery(this).css({
                        'left': ((100 /( groups.length))*i).toFixed(2) + '%'
                });
        });


        //inject and return
        sliderComponent
        .insertAfter(jQuery(this).eq(this.length-1))
        .slider(options.sliderOptions)
        .attr('role','application')
        .find('.ui-slider-label')
        .each(function(){
                jQuery(this).css('marginLeft', -jQuery(this).width()/2);
        });

        //update tooltip arrow inner color
        sliderComponent.find('.ui-tooltip-pointer-down-inner').each(function(){
                                var bWidth = jQuery('.ui-tooltip-pointer-down-inner').css('borderTopWidth');
                                var bColor = jQuery(this).parents('.ui-slider-tooltip').css('backgroundColor')
                                jQuery(this).css('border-top', bWidth+' solid '+bColor);
        });

        var values = sliderComponent.slider('values');

        if(isArray(values)){
                jQuery(values).each(function(i){
                        sliderComponent.find('.ui-slider-tooltip .ttContent').eq(i).text( ttText(this) );
                });
        }
        else {
                sliderComponent.find('.ui-slider-tooltip .ttContent').eq(0).text( ttText(values) );
        }

        return this;
}

/*
 ### jQuery Star Rating Plugin v3.13 - 2009-03-26 ###
 * Home: http://www.fyneworks.com/jquery/star-rating/
 * Code: http://code.google.com/p/jquery-star-rating-plugin/
 *
	* Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 ###
*/

/*# AVOID COLLISIONS #*/
;if(window.jQuery) (function($){
/*# AVOID COLLISIONS #*/
	
	// IE6 Background Image Fix
	if ($.browser.msie) try { document.execCommand("BackgroundImageCache", false, true)} catch(e) { };
	// Thanks to http://www.visualjquery.com/rating/rating_redux.html
	
	// plugin initialization
	$.fn.rating = function(options){
		if(this.length==0) return this; // quick fail
		
		// Handle API methods
		if(typeof arguments[0]=='string'){
			// Perform API methods on individual elements
			if(this.length>1){
				var args = arguments;
				return this.each(function(){
					$.fn.rating.apply($(this), args);
    });
			};
			// Invoke API method handler
			$.fn.rating[arguments[0]].apply(this, $.makeArray(arguments).slice(1) || []);
			// Quick exit...
			return this;
		};
		
		// Initialize options for this call
		var options = $.extend(
			{}/* new object */,
			$.fn.rating.options/* default options */,
			options || {} /* just-in-time options */
		);
		
		// Allow multiple controls with the same name by making each call unique
		$.fn.rating.calls++;
		
		// loop through each matched element
		this
		 .not('.star-rating-applied')
			.addClass('star-rating-applied')
		.each(function(){
			
			// Load control parameters / find context / etc
			var control, input = $(this);
			var eid = (this.name || 'unnamed-rating').replace(/\[|\]/g, '_').replace(/^\_+|\_+$/g,'');
			var context = $(this.form || document.body);
			
			// FIX: http://code.google.com/p/jquery-star-rating-plugin/issues/detail?id=23
			var raters = context.data('rating');
			if(!raters || raters.call!=$.fn.rating.calls) raters = { count:0, call:$.fn.rating.calls };
			var rater = raters[eid];
			
			// if rater is available, verify that the control still exists
			if(rater) control = rater.data('rating');
			
			if(rater && control)//{// save a byte!
				// add star to control if rater is available and the same control still exists
				control.count++;
				
			//}// save a byte!
			else{
				// create new control if first star or control element was removed/replaced
				
				// Initialize options for this raters
				control = $.extend(
					{}/* new object */,
					options || {} /* current call options */,
					($.metadata? input.metadata(): ($.meta?input.data():null)) || {}, /* metadata options */
					{ count:0, stars: [], inputs: [] }
				);
				
				// increment number of rating controls
				control.serial = raters.count++;
				
				// create rating element
				rater = $('<span class="star-rating-control"/>');
				input.before(rater);
				
				// Mark element for initialization (once all stars are ready)
				rater.addClass('rating-to-be-drawn');
				
				// Accept readOnly setting from 'disabled' property
				if(input.attr('disabled')) control.readOnly = true;
				
				// Create 'cancel' button
				rater.append(
					control.cancel = $('<div class="rating-cancel"><a title="' + control.cancel + '">' + control.cancelValue + '</a></div>')
					.mouseover(function(){
						$(this).rating('drain');
						$(this).addClass('star-rating-hover');
						//$(this).rating('focus');
					})
					.mouseout(function(){
						$(this).rating('draw');
						$(this).removeClass('star-rating-hover');
						//$(this).rating('blur');
					})
					.click(function(){
					 $(this).rating('select');
					})
					.data('rating', control)
				);
				
			}; // first element of group
			
			// insert rating star
			var star = $('<div class="star-rating rater-'+ control.serial +'"><a title="' + (this.title || this.value) + '">' + this.value + '</a></div>');
			rater.append(star);
			
			// inherit attributes from input element
			if(this.id) star.attr('id', this.id);
			if(this.className) star.addClass(this.className);
			
			// Half-stars?
			if(control.half) control.split = 2;
			
			// Prepare division control
			if(typeof control.split=='number' && control.split>0){
				var stw = ($.fn.width ? star.width() : 0) || control.starWidth;
				var spi = (control.count % control.split), spw = Math.floor(stw/control.split);
				star
				// restrict star's width and hide overflow (already in CSS)
				.width(spw)
				// move the star left by using a negative margin
				// this is work-around to IE's stupid box model (position:relative doesn't work)
				.find('a').css({ 'margin-left':'-'+ (spi*spw) +'px' })
			};
			
			// readOnly?
			if(control.readOnly)//{ //save a byte!
				// Mark star as readOnly so user can customize display
				star.addClass('star-rating-readonly');
			//}  //save a byte!
			else//{ //save a byte!
			 // Enable hover css effects
				star.addClass('star-rating-live')
				 // Attach mouse events
					.mouseover(function(){
						$(this).rating('fill');
						$(this).rating('focus');
					})
					.mouseout(function(){
						$(this).rating('draw');
						$(this).rating('blur');
					})
					.click(function(){
						$(this).rating('select');
					})
				;
			//}; //save a byte!
			
			// set current selection
			if(this.checked)	control.current = star;
			
			// hide input element
			input.hide();
			
			// backward compatibility, form element to plugin
			input.change(function(){
    $(this).rating('select');
   });
			
			// attach reference to star to input element and vice-versa
			star.data('rating.input', input.data('rating.star', star));
			
			// store control information in form (or body when form not available)
			control.stars[control.stars.length] = star[0];
			control.inputs[control.inputs.length] = input[0];
			control.rater = raters[eid] = rater;
			control.context = context;
			
			input.data('rating', control);
			rater.data('rating', control);
			star.data('rating', control);
			context.data('rating', raters);
  }); // each element
		
		// Initialize ratings (first draw)
		$('.rating-to-be-drawn').rating('draw').removeClass('rating-to-be-drawn');
		
		return this; // don't break the chain...
	};
	
	/*--------------------------------------------------------*/
	
	/*
		### Core functionality and API ###
	*/
	$.extend($.fn.rating, {
		// Used to append a unique serial number to internal control ID
		// each time the plugin is invoked so same name controls can co-exist
		calls: 0,
		
		focus: function(){
			var control = this.data('rating'); if(!control) return this;
			if(!control.focus) return this; // quick fail if not required
			// find data for event
			var input = $(this).data('rating.input') || $( this.tagName=='INPUT' ? this : null );
   // focus handler, as requested by focusdigital.co.uk
			if(control.focus) control.focus.apply(input[0], [input.val(), $('a', input.data('rating.star'))[0]]);
		}, // $.fn.rating.focus
		
		blur: function(){
			var control = this.data('rating'); if(!control) return this;
			if(!control.blur) return this; // quick fail if not required
			// find data for event
			var input = $(this).data('rating.input') || $( this.tagName=='INPUT' ? this : null );
   // blur handler, as requested by focusdigital.co.uk
			if(control.blur) control.blur.apply(input[0], [input.val(), $('a', input.data('rating.star'))[0]]);
		}, // $.fn.rating.blur
		
		fill: function(){ // fill to the current mouse position.
			var control = this.data('rating'); if(!control) return this;
			// do not execute when control is in read-only mode
			if(control.readOnly) return;
			// Reset all stars and highlight them up to this element
			this.rating('drain');
			this.prevAll().andSelf().filter('.rater-'+ control.serial).addClass('star-rating-hover');
		},// $.fn.rating.fill
		
		drain: function() { // drain all the stars.
			var control = this.data('rating'); if(!control) return this;
			// do not execute when control is in read-only mode
			if(control.readOnly) return;
			// Reset all stars
			control.rater.children().filter('.rater-'+ control.serial).removeClass('star-rating-on').removeClass('star-rating-hover');
		},// $.fn.rating.drain
		
		draw: function(){ // set value and stars to reflect current selection
			var control = this.data('rating'); if(!control) return this;
			// Clear all stars
			this.rating('drain');
			// Set control value
			if(control.current){
				control.current.data('rating.input').attr('checked','checked');
				control.current.prevAll().andSelf().filter('.rater-'+ control.serial).addClass('star-rating-on');
			}
			else
			 $(control.inputs).removeAttr('checked');
			// Show/hide 'cancel' button
			control.cancel[control.readOnly || control.required?'hide':'show']();
			// Add/remove read-only classes to remove hand pointer
			this.siblings()[control.readOnly?'addClass':'removeClass']('star-rating-readonly');
		},// $.fn.rating.draw
		
		
		
		
		
		select: function(value,wantCallBack){ // select a value
					
					// ***** MODIFICATION *****
					// Thanks to faivre.thomas - http://code.google.com/p/jquery-star-rating-plugin/issues/detail?id=27
					//
					// ***** LIST OF MODIFICATION *****
					// ***** added Parameter wantCallBack : false if you don't want a callback. true or undefined if you want postback to be performed at the end of this method'
					// ***** recursive calls to this method were like : ... .rating('select') it's now like .rating('select',undefined,wantCallBack); (parameters are set.)
					// ***** line which is calling callback
					// ***** /LIST OF MODIFICATION *****
			
			var control = this.data('rating'); if(!control) return this;
			// do not execute when control is in read-only mode
			if(control.readOnly) return;
			// clear selection
			control.current = null;
			// programmatically (based on user input)
			if(typeof value!='undefined'){
			 // select by index (0 based)
				if(typeof value=='number')
 			 return $(control.stars[value]).rating('select',undefined,wantCallBack);
				// select by literal value (must be passed as a string
				if(typeof value=='string')
					//return
					$.each(control.stars, function(){
						if($(this).data('rating.input').val()==value) $(this).rating('select',undefined,wantCallBack);
					});
			}
			else
				control.current = this[0].tagName=='INPUT' ?
				 this.data('rating.star') :
					(this.is('.rater-'+ control.serial) ? this : null);

			// Update rating control state
			this.data('rating', control);
			// Update display
			this.rating('draw');
			// find data for event
			var input = $( control.current ? control.current.data('rating.input') : null );
			// click callback, as requested here: http://plugins.jquery.com/node/1655
					
					// **** MODIFICATION *****
					// Thanks to faivre.thomas - http://code.google.com/p/jquery-star-rating-plugin/issues/detail?id=27
					//
					//old line doing the callback :
					//if(control.callback) control.callback.apply(input[0], [input.val(), $('a', control.current)[0]]);// callback event
					//
					//new line doing the callback (if i want :)
					if((wantCallBack ||wantCallBack == undefined) && control.callback) control.callback.apply(input[0], [input.val(), $('a', control.current)[0]]);// callback event
					//to ensure retro-compatibility, wantCallBack must be considered as true by default
					// **** /MODIFICATION *****
					
  },// $.fn.rating.select
		
		
		
		
		
		readOnly: function(toggle, disable){ // make the control read-only (still submits value)
			var control = this.data('rating'); if(!control) return this;
			// setread-only status
			control.readOnly = toggle || toggle==undefined ? true : false;
			// enable/disable control value submission
			if(disable) $(control.inputs).attr("disabled", "disabled");
			else     			$(control.inputs).removeAttr("disabled");
			// Update rating control state
			this.data('rating', control);
			// Update display
			this.rating('draw');
		},// $.fn.rating.readOnly
		
		disable: function(){ // make read-only and never submit value
			this.rating('readOnly', true, true);
		},// $.fn.rating.disable
		
		enable: function(){ // make read/write and submit value
			this.rating('readOnly', false, false);
		}// $.fn.rating.select
		
 });
	
	/*--------------------------------------------------------*/
	
	/*
		### Default Settings ###
		eg.: You can override default control like this:
		$.fn.rating.options.cancel = 'Clear';
	*/
	$.fn.rating.options = { //$.extend($.fn.rating, { options: {
			cancel: 'Cancel Rating',   // advisory title for the 'cancel' link
			cancelValue: '',           // value to submit when user click the 'cancel' link
			split: 0,                  // split the star into how many parts?
			
			// Width of star image in case the plugin can't work it out. This can happen if
			// the jQuery.dimensions plugin is not available OR the image is hidden at installation
			starWidth: 16//,
			
			//NB.: These don't need to be pre-defined (can be undefined/null) so let's save some code!
			//half:     false,         // just a shortcut to control.split = 2
			//required: false,         // disables the 'cancel' button so user can only select one of the specified values
			//readOnly: false,         // disable rating plugin interaction/ values cannot be changed
			//focus:    function(){},  // executed when stars are focused
			//blur:     function(){},  // executed when stars are focused
			//callback: function(){},  // executed when a star is clicked
 }; //} });
	
	/*--------------------------------------------------------*/
	
	/*
		### Default implementation ###
		The plugin will attach itself to file inputs
		with the class 'multi' when the page loads
	*/
	$(function(){
	 $('input[type=radio].star').rating();
	});
	
	
	
/*# AVOID COLLISIONS #*/
})(jQuery);
/*# AVOID COLLISIONS #*/

/*
 * Metadata - jQuery plugin for parsing metadata from elements
 *
 * Copyright (c) 2006 John Resig, Yehuda Katz, Jörn Zaefferer, Paul McLanahan
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 * Revision: $Id$
 *
 */

/**
 * Sets the type of metadata to use. Metadata is encoded in JSON, and each property
 * in the JSON will become a property of the element itself.
 *
 * There are three supported types of metadata storage:
 *
 *   attr:  Inside an attribute. The name parameter indicates *which* attribute.
 *          
 *   class: Inside the class attribute, wrapped in curly braces: { }
 *   
 *   elem:  Inside a child element (e.g. a script tag). The
 *          name parameter indicates *which* element.
 *          
 * The metadata for an element is loaded the first time the element is accessed via jQuery.
 *
 * As a result, you can define the metadata type, use $(expr) to load the metadata into the elements
 * matched by expr, then redefine the metadata type and run another $(expr) for other elements.
 * 
 * @name $.metadata.setType
 *
 * @example <p id="one" class="some_class {item_id: 1, item_label: 'Label'}">This is a p</p>
 * @before $.metadata.setType("class")
 * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
 * @desc Reads metadata from the class attribute
 * 
 * @example <p id="one" class="some_class" data="{item_id: 1, item_label: 'Label'}">This is a p</p>
 * @before $.metadata.setType("attr", "data")
 * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
 * @desc Reads metadata from a "data" attribute
 * 
 * @example <p id="one" class="some_class"><script>{item_id: 1, item_label: 'Label'}</script>This is a p</p>
 * @before $.metadata.setType("elem", "script")
 * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
 * @desc Reads metadata from a nested script element
 * 
 * @param String type The encoding type
 * @param String name The name of the attribute to be used to get metadata (optional)
 * @cat Plugins/Metadata
 * @descr Sets the type of encoding to be used when loading metadata for the first time
 * @type undefined
 * @see metadata()
 */

(function($) {

$.extend({
	metadata : {
		defaults : {
			type: 'class',
			name: 'metadata',
			cre: /({.*})/,
			single: 'metadata'
		},
		setType: function( type, name ){
			this.defaults.type = type;
			this.defaults.name = name;
		},
		get: function( elem, opts ){
			var settings = $.extend({},this.defaults,opts);
			// check for empty string in single property
			if ( !settings.single.length ) settings.single = 'metadata';
			
			var data = $.data(elem, settings.single);
			// returned cached data if it already exists
			if ( data ) return data;
			
			data = "{}";
			
			if ( settings.type == "class" ) {
				var m = settings.cre.exec( elem.className );
				if ( m )
					data = m[1];
			} else if ( settings.type == "elem" ) {
				if( !elem.getElementsByTagName ) return;
				var e = elem.getElementsByTagName(settings.name);
				if ( e.length )
					data = $.trim(e[0].innerHTML);
			} else if ( elem.getAttribute != undefined ) {
				var attr = elem.getAttribute( settings.name );
				if ( attr )
					data = attr;
			}
			
			if ( data.indexOf( '{' ) <0 )
			data = "{" + data + "}";
			
			data = eval("(" + data + ")");
			
			$.data( elem, settings.single, data );
			return data;
		}
	}
});

/**
 * Returns the metadata object for the first member of the jQuery object.
 *
 * @name metadata
 * @descr Returns element's metadata object
 * @param Object opts An object contianing settings to override the defaults
 * @type jQuery
 * @cat Plugins/Metadata
 */
$.fn.metadata = function( opts ){
	return $.metadata.get( this[0], opts );
};

})(jQuery);


/**
 * Cookie plugin
 *
 * Copyright (c) 2006 Klaus Hartl (stilbuero.de)
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 *
 */

/**
 * Create a cookie with the given name and value and other optional parameters.
 *
 * @example $.cookie('the_cookie', 'the_value');
 * @desc Set the value of a cookie.
 * @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true });
 * @desc Create a cookie with all available options.
 * @example $.cookie('the_cookie', 'the_value');
 * @desc Create a session cookie.
 * @example $.cookie('the_cookie', null);
 * @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain
 *       used when the cookie was set.
 *
 * @param String name The name of the cookie.
 * @param String value The value of the cookie.
 * @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
 * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
 *                             If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
 *                             If set to null or omitted, the cookie will be a session cookie and will not be retained
 *                             when the the browser exits.
 * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
 * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
 * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
 *                        require a secure protocol (like HTTPS).
 * @type undefined
 *
 * @name $.cookie
 * @cat Plugins/Cookie
 * @author Klaus Hartl/klaus.hartl@stilbuero.de
 */

/**
 * Get the value of a cookie with the given name.
 *
 * @example $.cookie('the_cookie');
 * @desc Get the value of a cookie.
 *
 * @param String name The name of the cookie.
 * @return The value of the cookie.
 * @type String
 *
 * @name $.cookie
 * @cat Plugins/Cookie
 * @author Klaus Hartl/klaus.hartl@stilbuero.de
 */
jQuery.cookie = function(name, value, options) {
    if (typeof value != 'undefined') { // name and value given, set cookie
        options = options || {};
        if (value === null) {
            value = '';
            options.expires = -1;
        }
        var expires = '';
        if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
            var date;
            if (typeof options.expires == 'number') {
                date = new Date();
                date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
            } else {
                date = options.expires;
            }
            expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
        }
        // CAUTION: Needed to parenthesize options.path and options.domain
        // in the following expressions, otherwise they evaluate to undefined
        // in the packed version for some reason...
        var path = options.path ? '; path=' + (options.path) : '';
        var domain = options.domain ? '; domain=' + (options.domain) : '';
        var secure = options.secure ? '; secure' : '';
        document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
    } else { // only name given, get cookie
        var cookieValue = null;
        if (document.cookie && document.cookie != '') {
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {
                var cookie = jQuery.trim(cookies[i]);
                // Does this cookie string begin with the name we want?
                if (cookie.substring(0, name.length + 1) == (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }
};

function mycarousel_initCallback(carousel)
{
    // Disable autoscrolling if the user clicks the prev or next button.
    carousel.buttonNext.bind('click', function() {
        carousel.startAuto(0);
    });

    carousel.buttonPrev.bind('click', function() {
        carousel.startAuto(0);
    });

    // Pause autoscrolling if the user moves with the cursor over the clip.
    carousel.clip.hover(function() {
        carousel.stopAuto();
    }, function() {
        carousel.startAuto();
    });
}

function fixToolTipColor()
{
	//grab the bg color from the tooltip content - set top border of pointer to same
	jQuery('.ui-tooltip-pointer-down-inner').each(function(){
		var bWidth = jQuery('.ui-tooltip-pointer-down-inner').css('borderTopWidth');
		var bColor = jQuery(this).parents('.ui-slider-tooltip').css('backgroundColor')
		jQuery(this).css('border-top', bWidth+' solid '+bColor);
	});	
}

function getResultsAjax(){
		// blockUI
		jQuery.blockUI({ 
			message: $('#loading')
		}); 
        //setTimeout(jQuery.unblockUI, 2200); 
		
		// set cookie
		$.cookie("dslvergleich_einstellungen", jQuery("form").serialize());

		
		//$.ajax({
		jQuery.ajax({
			url: "http://www.dsl-anbieter.com/ajax-response.php",
			type: "POST",
			cache: false,
			dataType: "script",
			data: jQuery("form").serialize(),
			error: function(){
				alert("Error loading XML document");
			},
			success: function(xml){
				// do something with xml
				if(jQuery.support.tbody == false){
									jQuery("#container_table_results").empty();
									jQuery("#container_table_results").append( xml );
									jQuery(".tt").cluetip({local:true, cursor: "pointer", dropShadow: false, width: 355}); 

				}
				else{											
					jQuery("#container_table_results").html( xml );
					jQuery(".tt").cluetip({local:true, cursor: "pointer", dropShadow: false, width: 355}); 
				}
				jQuery.unblockUI();
			}
			
		});

}

function limitChars(textid, limit, infodiv){
		var text = jQuery("#"+textid).val(); 
	 
		var textlength = text.length;
		
		if(textlength > limit){
			jQuery("#" + infodiv).html("0/"+limit+" Zeichen");
			jQuery("#"+textid).val(text.substr(0,limit));
			return false;
		}
		else {
			jQuery("#" + infodiv).html((limit - textlength) +"/1024 Zeichen.");
			return true;
		}
 }
 
 
 function alternateFormBewertung(){
 
	if(jQuery("#select_anbieterid").val() == "notfound"){
		jQuery('#select_anbieterid').parent().parent().next().show();
	}
	else{
		jQuery('#select_anbieterid').parent().parent().next().hide();
	}
 
 }
 
 
 
 function checkFormBewertung(){
 
	if((jQuery("#textkommentar").val() != "" && jQuery("#select_anbieterid").val() != "none") ||
		(jQuery("#textkommentar").val() != "" && jQuery("#select_anbieterid").val() == "notfound" && 
		jQuery('#select_anbieterid').parent().parent().next().children().first().next().val() != "")){
		var validated = true;
	}
	else{
		var validated = false;
	}
	
	// alert(jQuery('#select_anbieterid').parent().siblings().html());
	// jQuery('#select_anbieterid').parent().siblings().css('color', 'red');
	
	// alert(jQuery('#textkommentar').parent().parent().siblings().html());
	// jQuery('#textkommentar').parent().parent().siblings().css('color', 'red');
	
	
	// alert(jQuery('#select_anbieterid').parent().parent().after('<tr><td colspan="2">hallo</td></tr>'));
	
	
	if(validated === true){
	
		jQuery('#formular_bewertung').submit();
		
	}
	else{
		
		if(jQuery("#select_anbieterid").val() == "none"){
			jQuery('#select_anbieterid').parent().siblings().css('color', 'red');
		}
		else if(jQuery("#select_anbieterid").val() == "notfound" && 
				jQuery('#select_anbieterid').parent().parent().next().children().first().next().val() == ""){
				
			jQuery('#select_anbieterid').parent().parent().next().children().first().css('color', 'red');	
		
		}
		
		
		if(jQuery("#textkommentar").val() == ""){
			jQuery('#textkommentar').parent().parent().siblings().css('color', 'red');
		}
	}
	
	
	
 }


jQuery(document).ready(function()
{

	



     jQuery('#anbieterlogos').jcarousel( { scroll: 1, wrap: 'last' });

     /* TOBIS NAVI LOESUNG --------------------------------------------------------- */

     jQuery("#navigation li").hover(function(){
       jQuery(this).children("div").show(0);99
       jQuery(this).children("div").css('zIndex','999999999999999999999');
       jQuery("#tabs").css('zIndex','1');
       jQuery(".slider").css('zIndex','1');
       }, function() {
       jQuery(this).children("div").hide(0);
       });
       
    /* TOBIS TAB LOESUNG --------------------------------------------------------- */

    jQuery("#csstabs-list li a").hover(function(){
      jQuery("#csstabs-list li a").removeClass("csstabs-selected");
      jQuery(this).addClass("csstabs-selected");
      jQuery(".csstabs-single").hide();
      jQuery("#" + $(this).attr("id") + "-div").show();
    });

    /* TOBIS ENDE ---------------------------------------------------- */


    
    jQuery('.box_telefon').click( function() { if(jQuery('#checkbox_telefon').is(':checked') ) { jQuery('#checkbox_telefon').removeAttr('checked'); } else { jQuery('#checkbox_telefon').attr('checked','checked'); } });
    jQuery('.box_telekom').click( function() { if(jQuery('#checkbox_telekom').is(':checked') ) { jQuery('#checkbox_telekom').removeAttr('checked'); } else { jQuery('#checkbox_telekom').attr('checked','checked'); } });
    jQuery('.box_tv').click( function() { if(jQuery('#checkbox_tv').is(':checked') ) { jQuery('#checkbox_tv').removeAttr('checked'); } else { jQuery('#checkbox_tv').attr('checked','checked'); } });

	/*
		mit effektivem Kostenzeitraum!!
		
    if( jQuery('select#speed').length && jQuery('select#costs').length &&  jQuery('select#contractlifetime').length )
    {
	    jQuery('select#speed').selectToUISlider({ labels: '4', tooltip: false, labelSrc: 'text'});		
	    jQuery('select#costs').selectToUISlider({ labels: '5', tooltip: false, labelSrc: 'text'});		
	    jQuery('select#contractlifetime').selectToUISlider({ labels: '3', tooltip: false, labelSrc: 'text'});	
    }
	*/
	/* ohne effektiven kostenzeitraum*/
	if( jQuery('select#speed').length &&  jQuery('select#contractlifetime').length )
    {
	    jQuery('select#speed').selectToUISlider({ labels: '4', tooltip: false, labelSrc: 'text'});		
	    jQuery('select#contractlifetime').selectToUISlider({ labels: '3', tooltip: false, labelSrc: 'text'});	
    }
	
    
    jQuery('p.toggler').click( function()
    { 
    	if( jQuery('#morefilter').is(':hidden') )
    	{
    		jQuery(this).css("background-image", "url(http://www.dsl-anbieter.com/images/toggle_close.gif)");
    		jQuery('#morefilter').slideDown();
    	}
    	else
    	{
    		jQuery(this).css("background-image", "url(http://www.dsl-anbieter.com/images/toggle_open.gif)");
        	jQuery('#morefilter').slideUp();
    	}
    	
    });
	
	
	jQuery('p.toggler_tarifzeile').live('click', function()
    { 
    	if( jQuery(this).parents("tr").next().is(':hidden') )
    	{
    		jQuery(this).css("background-image", "url(http://www.dsl-anbieter.com/images/toggle_close.gif)");
			jQuery(this).parents("tr").next().slideDown();
    	}
    	else
    	{
    		jQuery(this).css("background-image", "url(http://www.dsl-anbieter.com/images/toggle_open.gif)");
			jQuery(this).parents("tr").next().slideUp();
    	}
    			
    });
	jQuery('p.toggler_tarifzeile_test').live('click', function()
    { 
    	if( jQuery(this).parents("tr").next().is(':hidden') )
    	{
    		//jQuery(this).css("background-image", "url(http://www.dsl-anbieter.com/images/toggle_close.gif)");
			jQuery(this).parents("tr").next().slideDown();
    		jQuery(this).children('img').first().attr("src","http://www.dsl-anbieter.com/images/toggle_close.gif");
			
			//jQuery(this).parent().parent().parent().siblings().first().next().children().first().children().first().next().next().next().next().children('span').first().children('img').first().attr('src', 'http://www.dsl-anbieter.com/images/toggle_close.gif');
    	}
    	else
    	{
    		//jQuery(this).css("background-image", "url(http://www.dsl-anbieter.com/images/toggle_open.gif)");
			jQuery(this).parents("tr").next().slideUp();
    		jQuery(this).children('img').first().attr("src","http://www.dsl-anbieter.com/images/toggle_open.gif");
			
			//jQuery(this).parent().parent().parent().siblings().first().next().children().first().children().first().next().next().next().next().children('span').first().children('img').first().attr('src', 'http://www.dsl-anbieter.com/images/toggle_open.gif');
    	}
    	
    });
	jQuery('.toggle_hardwarezeile').live('click', function(){
		
		jQuery(this).parents('td').parents('tr').children().first().children().first().children().last().children('.toggler_tarifzeile_test').click();
	});
    
    jQuery('ul#filter').children('li').click( function()
    {
    	var theID = 'val_' + jQuery(this).children('p').attr('class');
    	var theIDVal = jQuery('#' + theID).val();
    	
    	if( theIDVal == 0 )
    	{
    		jQuery(this).css("background-image", "url(http://www.dsl-anbieter.com/images/clickbutton_bg_on.gif)");
    		jQuery('#' + theID).val(1);
    	}
    	else
    	{
    		jQuery(this).css("background-image", "url(http://www.dsl-anbieter.com/images/clickbutton_bg.gif)");
    		jQuery('#' + theID).val(0);
    	}
    });
    
    if( jQuery('.tt').length )
    {
    	jQuery('.tt').cluetip({local:true, cursor: 'pointer', dropShadow: false, width: 355});       
    }
    
    if( jQuery('.hlp').length )
    {
    	jQuery('.hlp').cluetip({splitTitle: '|'});
    }
    
    jQuery('span.checklabel').click( function()
    {
    	var obj = jQuery(this).prev('input.checkbox');
    	
    	if( obj.is(':checked') )
    	{
    		obj.removeAttr('checked');
    	
    	}else{
    		obj.attr('checked','checked')
    	}
			getResultsAjax();
    			
    });
    
        /*
        jQuery(".tab_content").hide();
	jQuery("ul.tabs li:first").addClass("active").show(); 
	//jQuery(".tabblock_tab1").show();
	jQuery(".tabblock_dsl").show(); 
	*/
	
	var myurl = document.location.toString();
	
	if (myurl.match('#'))
	{
		var myAnchor = '.tabblock_' + myurl.split('#')[1];
		var myAnchorTab = '#' + myurl.split('#')[1];
		                                         
		jQuery(".tab_content").hide(); 
		jQuery(myAnchor).show(0);
		
		jQuery("ul.tabs li").removeClass("active");
		jQuery("a[href|="+myAnchorTab+"]").parent().addClass("active");		
	}

	jQuery("ul.tabs li").click(function() {
		jQuery("ul.tabs li").removeClass("active");
		jQuery(this).addClass("active"); 
		jQuery(".tab_content").hide();
		var activeTab = jQuery(this).find("a").attr("href");

		activeTab = '.tabblock_' + activeTab.substr(1);
		
		jQuery(activeTab).fadeIn();
	});

	
	
	jQuery('span.toggle_link').click( function()
	{
		if( jQuery('div.toggle_content').is(':hidden') == true )
		{
			jQuery('div.toggle_content').slideDown(200);
			jQuery(this).html('ausblenden');
		}else{
			jQuery('div.toggle_content').slideUp(200);
			jQuery(this).html('mehr lesen');
		}
	});
	
	var austDay = new Date(2012, 01, 30);

	jQuery('#countdown').countdown({until: austDay, compact: true, layout: '<div class="image{d10}"></div><div class="image{d1}"></div><div class="imageDay"></div><div class="imageSpace"></div><div class="image{h10}"></div><div class="image{h1}"></div><div class="imageSep"></div><div class="image{m10}"></div><div class="image{m1}"></div><div class="imageSep"></div><div class="image{s10}"></div><div class="image{s1}"></div>' });


		$('.l_01').click(function(){window.location="http://www.dsl-anbieter.com/internet-anbieter/"});

	$('.l_02').click(function(){window.location="http://www.dsl-anbieter.com/dsl-vergleich/"});

	$('.l_03').click(function(){window.location="http://www.dsl-anbieter.com/umts-tarif-vergleich/"});

	$('.l_04').click(function(){window.location="http://www.dsl-anbieter.com/umts-flatrate/"});

	$('.l_05').click(function(){window.location="http://www.dsl-anbieter.com/umts-tarif-vergleich/"});

	$('.l_18').click(function(){window.location="http://www.dsl-anbieter.com/dsl-magazin/dsl-lexikon"});

	$('.l_19').click(function(){window.location="http://www.dsl-anbieter.com/dsl-magazin/dsl-themen/absicherung-des-wlan-netztes-leicht-gemacht0805201001.html"});

	$('.l_20').click(function(){window.location="http://www.dsl-anbieter.com/dsl-magazin/dsl-themen/sonderkundigungsrecht-bei-zu-geringer-dsl-geschwindigkeit.html"});

	$('.l_21').click(function(){window.location="http://www.dsl-anbieter.com/kabel-dsl/"});

	$('.l_22').click(function(){window.location="http://www.dsl-anbieter.com/kabel-anbieter/"});

	$('.l_news0').click(function(){window.location="http://www.dsl-anbieter.com/dsl-magazin/dsl-news/1und1"});

	$('.l_news1').click(function(){window.location="http://www.dsl-anbieter.com/dsl-magazin/dsl-news/alice"});

	$('.l_news2').click(function(){window.location="http://www.dsl-anbieter.com/dsl-magazin/dsl-news/allgemein"});

	$('.l_news3').click(function(){window.location="http://www.dsl-anbieter.com/dsl-magazin/dsl-news/congstar"});

	$('.l_news4').click(function(){window.location="http://www.dsl-anbieter.com/dsl-magazin/dsl-news/duffy-fon"});

	$('.l_news5').click(function(){window.location="http://www.dsl-anbieter.com/dsl-magazin/dsl-news/kabel-deutschland"});

	$('.l_news6').click(function(){window.location="http://www.dsl-anbieter.com/dsl-magazin/dsl-news/kabelbw"});

	$('.l_news7').click(function(){window.location="http://www.dsl-anbieter.com/dsl-magazin/dsl-news/o2"});

	$('.l_news8').click(function(){window.location="http://www.dsl-anbieter.com/dsl-magazin/dsl-news/t-home"});

	$('.l_news9').click(function(){window.location="http://www.dsl-anbieter.com/dsl-magazin/dsl-news/tele2"});

	$('.l_news10').click(function(){window.location="http://www.dsl-anbieter.com/dsl-magazin/dsl-news/telekom"});

	$('.l_news11').click(function(){window.location="http://www.dsl-anbieter.com/dsl-magazin/dsl-news/unitymedia"});

	$('.l_news12').click(function(){window.location="http://www.dsl-anbieter.com/dsl-magazin/dsl-news/versatel"});

	$('.l_news13').click(function(){window.location="http://www.dsl-anbieter.com/dsl-magazin/dsl-news/vodafone"});

	
	
	

	$('.topnav_news').click(function(){window.location="http://www.dsl-anbieter.com/dsl-magazin/dsl-news/"});

	$('.topnav_lexikon').click(function(){window.location="http://www.dsl-anbieter.com/dsl-magazin/dsl-lexikon/"});

	$('.topnav_themen').click(function(){window.location="http://www.dsl-anbieter.com/dsl-magazin/dsl-themen/"});

	$('.topnav_ratgeber').click(function(){window.location="http://www.dsl-anbieter.com/dsl-ratgeber/"});

	
	$('.single-tab').hover( function() { $(this).css( 'cursor', 'pointer' ); });

	$('.link_tab1').click(function(){window.location="http://www.dsl-anbieter.com/dsl-speedtest/"});
	$('.link_tab2').click(function(){window.location="http://www.dsl-anbieter.com/dsl-vergleich/"});	
	$('.link_tab3').click(function(){window.location="http://www.dsl-anbieter.com/internet-anbieter/"});	
	$('.link_tab4').click(function(){window.location="http://www.dsl-anbieter.com/dsl-ratgeber/dsl-verfuegbarkeit.html"});
	$('.link_tab5').click(function(){window.location="http://www.dsl-anbieter.com/dsl-angebote/"});
	$('.link_tab6').click(function(){window.location="http://www.dsl-anbieter.com/dsl-magazin/"});
	$('.link_tab7').click(function(){window.location="http://www.dsl-anbieter.com/lte/"});
	
	if(!jQuery(".tarif_ohne_mvlz").length){
			
			jQuery("#tariftab_ohne_mvlz").hide();
			jQuery("#tariftab_mit_mvlz").addClass("active");
		}
		else{
			jQuery(".tarif_ohne_mvlz").hide();
			jQuery("#tariftab_mit_mvlz").addClass("active");
		
			jQuery("#tariftab_ohne_mvlz").click(function(){

				jQuery(".tarif_mit_mvlz").hide("fast");
				jQuery(".tarif_ohne_mvlz").show("fast");
				jQuery("#tariftab_mit_mvlz").removeClass("active");
				jQuery("#tariftab_ohne_mvlz").addClass("active");
			
			});
			jQuery("#tariftab_mit_mvlz").click(function(){
			
				jQuery(".tarif_ohne_mvlz").hide("fast");
				jQuery(".tarif_mit_mvlz").show("fast");
				jQuery("#tariftab_mit_mvlz").addClass("active");
				jQuery("#tariftab_ohne_mvlz").removeClass("active");
			
			});
		}
		
		
		jQuery("#bewertungsformular").toggle();
			
			
				jQuery("#slick-toggle").click(function() {

					jQuery("#bewertungsformular").toggle(400);
					jQuery("#bewertungsausgabe").toggle();
					// use slide down
					return false;

				  });
				  
				jQuery("#textkommentar").keyup(function(){

					limitChars("textkommentar", 1024, "restzeichen");

				});
				
				/* DSL-Flat als Vorsteuerung festlegen (nur optisch, tatsächliche Vorsteuerung erfolgt in inc.form-validation-neu.php */
				jQuery("ul#filter").children("li").eq(0).css("background-image", "url(http://www.dsl-anbieter.com/images/clickbutton_bg_on.gif)");
				jQuery("#" + "val_" + jQuery("ul#filter").children("li").eq(0).children("p").attr("class")).val(1);
			
				/* Telefon-Flat als Vorsteuerung festlegen (nur optisch, tatsächliche Vorsteuerung erfolgt in inc.form-validation-neu.php */
				jQuery("ul#filter").children("li").eq(1).css("background-image", "url(http://www.dsl-anbieter.com/images/clickbutton_bg_on.gif)");
				jQuery("#" + "val_" + jQuery("ul#filter").children("li").eq(1).children("p").attr("class")).val(1);

			
				jQuery("ul#filter").children("li").eq(1).click(function(){
					getResultsAjax();				
				});
				jQuery("ul#filter").children("li").eq(2).click(function(){
					getResultsAjax();				
				});
				jQuery("ul#filter").children("li").eq(3).click(function(){
					getResultsAjax();				
				});
				/* Funkionalität der DSL-Flat Checkbox unterbinden. Es ist optisch immer ausgewählt.*/ 
				jQuery("ul#filter").children("li").eq(0).click(function(){
					jQuery("ul#filter").children("li").eq(0).css("background-image", "url(http://www.dsl-anbieter.com/images/clickbutton_bg_on.gif)");
					jQuery("#" + "val_" + jQuery("ul#filter").children("li").eq(0).children("p").attr("class")).val(1);
				});

				
				jQuery(".slider").bind("slidechange", function(e, ui) {
 
					//alert("Änderung wurde vorgenommen");

						getResultsAjax();
 
				});
		
		jQuery("#sidebar_preisvergleich_button").click(function(){
		
			// sidebar_preisvergleich_form
			
			// alert(jQuery("#sidebar_preisvergleich_button").closest("form").serialize());
			
			jQuery("#sidebar_preisvergleich_button").closest("form").submit();
		
		});
	
		jQuery("#form_dslvergleich").change(function(){
		
			//S$.cookie("dslvergleich_einstellungen", jQuery("form").serialize());
		
			getResultsAjax();	
		});
		

		
		jQuery("#input_newsletter").click(function(){
				
			if(jQuery("#input_newsletter").val() == "Ihre E-Mail Adresse"){
			
				jQuery("#input_newsletter").val("");
			 }
			
		
		});
		
		
		jQuery(".button_neuberechnen").live('click', function(){
			// fire click auf .radio_neuberechnen!	
			jQuery(this).parent().prev().children().click();
		});
		
		
		
		jQuery(".radio_neuberechnen").live('click', function(){
		
			var nameHardware = jQuery(this).parent().next().children().html();
			var tabellenzeileHardware = jQuery(this).parent().parent();
			tabellenzeileHardware.addClass("weitereinfos_zeileaktiv");
			tabellenzeileHardware.siblings().removeClass("weitereinfos_zeileaktiv");
			
			if(nameHardware!="keine Hardware"){
				
				var preisHardware_mtl = jQuery(this).parent().next().next().next().html();
				var preisHardware_einml = jQuery(this).parent().next().next().html();

				
				preisHardware_mtl = preisHardware_mtl.replace(" EUR","");
				var preisHardware_mtl_komma = preisHardware_mtl;
				
				preisHardware_mtl = preisHardware_mtl.replace(",",".");
				preisHardware_mtl = parseFloat(preisHardware_mtl);
				
				preisHardware_einml = preisHardware_einml.replace(" EUR","");
				var preisHardware_einml_komma = preisHardware_einml;
				
				preisHardware_einml = preisHardware_einml.replace(",",".");
				preisHardware_einml = parseFloat(preisHardware_einml);
				
				
					var effektiverPreis = jQuery(this).closest(".weitereinfos_tarifzeile").prev("tr").children().last().children().first().children("table").children("tbody").children().last().prev().prev().children().html();
					effektiverPreis = effektiverPreis.replace(" EUR","");
					effektiverPreis = effektiverPreis.replace(",",".");
					effektiverPreis = parseFloat(effektiverPreis);
						
					var neuerPreis = effektiverPreis + preisHardware_mtl;

					if(preisHardware_einml != 0){
						neuerPreis = effektiverPreis + (preisHardware_einml/24);
					}
					
					neuerPreis = (Math.round(neuerPreis * 100)/100);
					var differenzPreis = (Math.round((neuerPreis - effektiverPreis)* 100)/100);
					
					
					neuerPreis = neuerPreis+"";
					neuerPreis = neuerPreis.replace(".",",");
					
					if(neuerPreis.length < 4){
						neuerPreis = neuerPreis+",00";
					}
					if(neuerPreis.length == 4){
						neuerPreis = neuerPreis+"0";
					}
					
					differenzPreis = differenzPreis+"";
					
					if(differenzPreis == "0"){
						differenzPreis = "0,00";
					}
					else{
						if(differenzPreis.length == 1){
							differenzPreis = differenzPreis+",00";
						}
						if(differenzPreis.length == 3){
							differenzPreis = differenzPreis+"0";
						}
						
					}
					differenzPreis = differenzPreis.replace(".",",");
					
					
					jQuery(this).closest(".weitereinfos_tarifzeile").prev("tr").children().last().children(".price").html(neuerPreis+" EUR");
					jQuery(this).closest(".weitereinfos_tarifzeile").prev("tr").children().last().children().first().children("table").children("tbody").children().last().prev().children().last().html(neuerPreis+" &euro;");
					
					jQuery(this).closest(".weitereinfos_tarifzeile").prev("tr").children().last().children().first().children("table").children("tbody").children().last().prev().prev().prev().html('<td class="tt_left">Hardware ('+nameHardware+')</td><td class="tt_center">'+preisHardware_einml_komma+' &euro;</td><td class="tt_right">'+preisHardware_mtl_komma+' &euro;</td>');
					
					jQuery(this).parent().next().next().next().next().html(neuerPreis+" EUR <span style=\"font-size:0.9em;\">("+differenzPreis+" EUR zus&auml;tzlich im Monat)</span>");
					
					//var hardwareBildpfad = jQuery(this).parent().next().next().next().next().html();
					//alert(hardwareBildpfad);
					//jQuery(this).closest(".hardware_bild").html('<img src="'+hardwareBildpfad+'" />');
					//jQuery(this).closest(".new_price").html(neuerPreis+" EUR (+ "+differenzPreis+" EUR im Monat)");
				
					//alert(jQuery(this).parent().parent().parent().parent().parent().parent().children().last().html());
					
					//jQuery(this).parent().parent().parent().parent().parent().parent().children().last().prev().html('<img src="'+hardwareBildpfad+'" />');
					//jQuery(this).parent().parent().parent().parent().parent().parent().children().last().html(neuerPreis+" EUR (+ "+differenzPreis+" EUR im Monat)");
			}
			else{
				
				var effektiverPreis = jQuery(this).closest(".weitereinfos_tarifzeile").prev("tr").children().last().children().first().children("table").children("tbody").children().last().prev().prev().children().html();
					
				jQuery(this).closest(".weitereinfos_tarifzeile").prev("tr").children().last().children(".price").html(effektiverPreis+" EUR");
				jQuery(this).closest(".weitereinfos_tarifzeile").prev("tr").children().last().children().first().children("table").children("tbody").children().last().prev().children().last().html(effektiverPreis+" &euro;");
				jQuery(this).closest(".weitereinfos_tarifzeile").prev("tr").children().last().children().first().children("table").children("tbody").children().last().prev().prev().prev().html('<td colspan="3" style="display:none;"></td>');
				
				tabellenzeileHardware.removeClass("weitereinfos_zeileaktiv");
			}
			
		});
		
		
		
		jQuery("#anschluss_auswahl").change(function(){
			
			// parent tr
			//alert(selectField.parent().parent().html());
			
			// td beschreibung (telefonvorwahl)
			//alert(selectField.parent().parent().next().next().children().first().html());
			
			// if td bereits eingefügt...
			//alert(selectField.parent().parent().next().next().children().length);
			
			
			//selectField.parent().parent().next().next().children().first().after('<td colspan="2"><input type="text" name="vorwahl" size="6" /></td>');
			//selectField.parent().parent().next().next().children().first().after('<td><input type="text" name="vorwahl" size="6" /></td><td style="padding-left:10px;"><input type="text" name="rufnummer" size="30"/></td>');
			
			
			var selectField = jQuery("#anschluss_auswahl");
			// tr in nächste table
			//alert(selectField.parent().parent().parent().parent().next().children().children().first().html());
			
			if(selectField.val() == "Neuanschluss"){
				
				//selectField.parent().parent().next().next().html('<td style="text-align:right;">Telefonvorwahl</td><td colspan="2"><input type="text" name="vorwahl" size="6" /></td>');
				selectField.parent().parent().parent().parent().next().children().children().first().html('<td style="text-align:right;">Telefonvorwahl</td><td colspan="2"><input type="text" name="vorwahl" size="6" /></td>');
			
			}
			if(selectField.val() == "Tarifwechsel"){
			
				//selectField.parent().parent().next().next().html('<td style="text-align:right;">Telefonvorwahl / Rufnummer</td><td><input type="text" name="vorwahl" size="6" /></td><td style="padding-left:10px;"><input type="text" name="rufnummer" size="30"/></td>');
				selectField.parent().parent().parent().parent().next().children().children().first().html('<td style="text-align:right;">Telefonvorwahl / Rufnummer</td><td><input type="text" name="vorwahl" size="6" /></td><td style="padding-left:10px;"><input type="text" name="rufnummer" size="30"/></td>');
			
			}
			
			jQuery(".tr_hidden").show('slow');
			
		});
		
		if(window.location == "http://www.dsl-anbieter.com/" || window.location == "http://www.dsl-anbieter.com/index.php" || window.location == "http://www.dsl-anbieter.com/dsl-tarife/dsl-flatrate.html"){
			jQuery(".ui-slider-horizontal").css("width","240px");
		}

	
});

