

	_scalendar_days = new Array('Su', 'M', 'Tu', 'W', 'Th', 'F', 'Sa');
	_scalendar_full_days = new Array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday');
	_scalendar_months = new Array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December');
	_scalendar_short_months = new Array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');

	_scalendar_start_day = 1;

	_scalendar_selected = new Array();
	_scalendar_dates = new Array();


	function scalendar_draw_month ( month, year, name ) {
		// draws a scalendar month html
		// ----------------------------
		// function takes in the actual month number (1-12)
		// but then all date references further from this use the javascript version of the month (0-11)

		if (!name) {
			var name = 'scalendar';
		}
		if (!array_key_exists(name, _scalendar_dates)) {
			_scalendar_dates[name] = new Array();
		}
		if (!array_key_exists(name, _scalendar_selected)) {
			_scalendar_selected[name] = new Array();
		}

		// first work out month data	

		// get first day of month
		var first = new Date(year, month-1, 1); // (javascript months are from 0 to 11)
		// work out start day
		var fday = first.getDay();
		// days in month
		var cdays = scalendar_days_in_month(first)


		// work out previous month values
		var pdays = 0;

		// is previous month needed on table?
		if (fday != _scalendar_start_day) {
			//alert('previous month required');

			// how many days are required?
			pdays = fday - _scalendar_start_day;
			if (pdays < 0) {
				pdays += 7;
			}

			// what day of previous month to start at
			var pmonth = scalendar_get_previous_month(first);
			pmonth.setDate(scalendar_days_in_month(pmonth) - pdays + 1); // days in month - required slots + 1

			//alert('starting at '+pmonth.toString()+' for '+pdays+' days');
		}


		// work out next month values
		var ndays = 0;

		// work out _scalendar_end_day
		var _scalendar_end_day = _scalendar_start_day - 1;
		if (_scalendar_end_day < 0) {
			_scalendar_end_day = 6;
		}

		// work out last day of current month
		var last = new Date(year, month-1, cdays);
		var lday = last.getDay();

		// is next month needed on table?
		if (lday != _scalendar_end_day) {
			//alert('next month required');

			// how many days are required
			ndays = _scalendar_end_day - lday;
			if (ndays < 0) {
				ndays += 7;
			}

			// get next month object to start at
			var nmonth = scalendar_get_next_month(first);
			nmonth.setDate(1);

			//alert('starting at '+nmonth.toString()+' for '+ndays+' days');
		}


		// now that we have the required month data, we can draw the scalendar!
		var d = '';

		// cell counters
		var column = 0;
		var row = 0;
		var dow = _scalendar_start_day;

		// get name to use for this calendar
		var cname = year+'-'+(month-1);

		// header
		d += '<div class="title">'+_scalendar_months[month-1]+' '+year+'</div>';
		d += '	<table><tr><td class="outer"><div class="outer">';
		d += '		<table class="scalendar">';
		d += '			<tr class="days">';

		// day headings
		var i = _scalendar_start_day;
		while (true) {
			d += '<th';
			if (i == 6 || i == 0) {
				d += ' class="th-w"';
			}
			d += '>'+_scalendar_days[i]+'</th>';
			if (i == _scalendar_end_day) {
				break;
			}
			i++;
			if (i > 6) {
				i = 0;
			}
		}

		d += '			</tr>';
		d += '			<tr>';

		// go through previous month?
		if (pdays > 0) {
			for (var i = pmonth.getDate(); i < pmonth.getDate()+pdays; i++) {
				d += scalendar_draw_cell(name, i, dow, false, cname, pmonth.getFullYear()+'-'+pmonth.getMonth()+'-'+i);
				column++;
				dow++;
				if (dow == 7) {
					dow = 0;
				}
			}
		}

		// go through current month
		for (var i = 1; i <= cdays; i++) {
			d += scalendar_draw_cell(name, i, dow, true, cname, year+'-'+(month-1)+'-'+i);
			column++;
			if (column == 7) {
				d += '			</tr>';
				d += '			</tr>';
				column = 0;
				row++;
			}
			dow++;
			if (dow == 7) {
				dow = 0;
			}
		}

		// go through next month?
		if (ndays > 0) {
			for (var i = 1; i <= ndays; i++) {
				d += scalendar_draw_cell(name, i, dow, false, cname, nmonth.getFullYear()+'-'+nmonth.getMonth()+'-'+i);
				column++;
				dow++;
				if (dow == 7) {
					dow = 0;
				}
			}
		}

		// footer
		d += '			</tr>';
		d += '		</table>';
		d += '	</div></td></tr></table>';

		document.write(d);

	}


	// function for drawing a cell
	function scalendar_draw_cell ( name, i, dow, thismonth, cname, cdate ) {
		// work out class
		var c = '';
		if (!thismonth) {
			c += 'p';
		}
		if (dow == 0 || dow == 6) {
			c += 'w';
		}
		// is selected?
		var s = '';
		if (array_in_array(cdate, _scalendar_selected) != -1) {
			s = 's';
		}
		// add cell to array
		if (!array_key_exists(cdate, _scalendar_dates[name])) {
			_scalendar_dates[name][cdate] = new Array();
		}
		if (!array_key_exists(cname, _scalendar_dates[cdate])) {
			_scalendar_dates[name][cdate][cname] = new Array();
		}
		_scalendar_dates[name][cdate][cname]['class'] = c;
		// draw cell
		return '<td id="'+name+'_'+cname+'_'+cdate+'" class="disableselect '+s+c+'" onmouseover="scalendar_cell_over(this);" onclick="scalendar_cell_click(this);" onselectstart="return false;">'+i+'</td>';
	}



	// functions for handling cell overs and outs
	function scalendar_cell_over ( obj ) {
		var a = obj.id.split('_');
		if (array_in_array(a[2], _scalendar_selected[a[0]]) != -1) { return; }
		var c = _scalendar_dates[a[0]][a[2]][a[1]]['class'];
		var fc = '#e7cfcf';
		var col = '#ffffff';
		if (c == 'p' || c == 'pw') {
			fc = '#eadede';
		}
		if (c == 'w' || c == 'pw') {
			col = '#fef7d8';
		}
		if ($(obj).is(':animated')) {
			$(obj).stop();
		}
		$(obj).css('background-color', fc);
		$(obj).animate({backgroundColor: col}, 300);
	}


	// function for handling cell click
	function scalendar_cell_click ( obj ) {
		var a = obj.id.split('_');
		var c = '';
		var k = array_in_array(a[2], _scalendar_selected[a[0]]);
		if (k == -1) {
			// is unselected, now select
			_scalendar_selected[a[0]][_scalendar_selected[a[0]].length] = a[2];
			c = 's';
		} else {
			// is selected, now unselect
			_scalendar_selected[a[0]].splice(k, 1);
		}
		// loop through all instances of date and change class
		for (var i in _scalendar_dates[a[0]][a[2]]) {
			if (typeof(_scalendar_dates[a[0]][a[2]][i]) != 'object') { continue; }
			if (!document.getElementById(a[0]+'_'+i+'_'+a[2])) { continue; }
			var td = $('#'+a[0]+'_'+i+'_'+a[2]);
			if (td.is(':animated')) {
				td.stop();
			}
			var c = _scalendar_dates[a[0]][a[2]][i]['class'];
			if (k == -1) {
				var col = '#fbde5a';
				if (c == 'p' || c == 'pw') {
					col = '#f2e194';
				}
			} else {
				var col = '#ffffff';
				if (c == 'w' || c == 'pw') {
					col = '#fef7d8';
				}
			}
			td.animate({backgroundColor: col}, 200);

		}
		// write dates to form
		scalendar_write_dates_to_form(a[0]);
	}



	// function for updating form with dates
	function scalendar_write_dates_to_form ( name ) {
		var v = '';
		var h = '';
		if (_scalendar_selected[name].length > 0) {
			var aa = new Array();
			for (var i = 0; i < _scalendar_selected[name].length; i++) {
				var ab = _scalendar_selected[name][i].split('-');
				var ac = new Date(ab[0], ab[1], ab[2]);
				aa[aa.length] = ac.getTime();
			}
			aa.sort();
			var o = new Array();
			var p = new Array();
			for (var i = 0; i < aa.length; i++) {
				var a = new Date(aa[i]);
				o[o.length] = scalendar_proper_date(a);
				p[p.length] = scalendar_display_date(a);
			}
			v = o.join(',');
			h = p.join('<br />');
		}
		document.getElementById('scalendar-form-dates_'+name).value = v;
		var d = $('#scalendar-display-dates_'+name);
		if (h == '') {
			d.css('color', '#b12b1a');
			d.css('font-style', 'italic');
			d.html('show all');
		} else {
			d.css('color', 'black');
			d.css('font-style', 'normal');
			d.html(h);
		}
	}


	// function for use onload for selecting dates already in form
	function scalendar_get_dates_from_form ( name ) {
		if (!document.getElementById('scalendar-form-dates_'+name)) { return; }
		var a = document.getElementById('scalendar-form-dates_'+name).value;
		a = a.split(',');
		for (var j = 0; j < a.length; j++) {

			// skip if blank
			if (a[j] == '') { continue; }

			// get js version of date
			var d = scalendar_js_date(a[j]);

			// add to selected array if not already there
			if (array_in_array(d, _scalendar_selected[name]) == -1) {
				_scalendar_selected[name][_scalendar_selected[name].length] = d;
			}

			// loop through all instances of date and change class
			for (var i in _scalendar_dates[name][d]) {
				if (typeof(_scalendar_dates[name][d][i]) != 'object') { continue; }
				if (!document.getElementById(name+'_'+i+'_'+d)) { continue; }
				var c = _scalendar_dates[name][d][i]['class'];
				var col = '#fbde5a';
				if (c == 'p' || c == 'pw') {
					col = '#f2e194';
				}
				document.getElementById(name+'_'+i+'_'+d).style.backgroundColor = col;
			}

		}
		scalendar_write_dates_to_form(name);
	}

	// function for clearing the scalendar form (used on initial load)
	function scalendar_clear_form () {
		if (document.getElementById('scalendar-form-dates')) {
			if (document.getElementById('scalendar-keep-dates')) {
				document.getElementById('scalendar-form-dates').value = '';
			}
		}
	}

	// scalendar's onload function
	function scalendar_load () {
		scalendar_flush(true);
	}

	// function for getting calendar data from input field
	// it's run once at document ready, but with clearing turned off
	// and then run again on final load with clearing enabled
	function scalendar_flush ( clear ) {
		for (var i in _scalendar_dates) {
			if (document.getElementById('scalendar-form-dates_'+i)) {
				if (document.getElementById('scalendar-keep-dates_'+i)) {
					scalendar_get_dates_from_form(i);
				} else {
					if (clear) {
						document.getElementById('scalendar-form-dates_'+i).value = '';
					}
				}
			}
		}
	}


	// function for returning the previous month object of a date object
	function scalendar_get_previous_month ( d ) {
		var month = d.getMonth();
		var year = d.getFullYear();
		var day = d.getDate();
		month--;
		if (month < 0) {
			month = 11;
			year--;
		}
		var a = new Date(year, month, day);
		return a;
	}

	// function for returning the next month object of a date object
	function scalendar_get_next_month ( d ) {
		var month = d.getMonth();
		var year = d.getFullYear();
		var day = d.getDate();
		month++;
		if (month > 11) {
			month = 0;
			year++;
		}
		var a = new Date(year, month, day);
		return a;
	}


	// function to work out how many days in the month of a date object
	function scalendar_days_in_month ( d ) {
		var month = d.getMonth();
		var year = d.getYear();
		var m = [31,28,31,30,31,30,31,31,30,31,30,31];
		if (month != 1) return m[month];
		if (year%4 != 0) return m[1];
		if (year%100 == 0 && year%400 != 0) return m[1];
		return m[1] + 1;
	} 

	// function to turn a mysql date in to a javascript format date
	function scalendar_js_date ( d ) {
		var a = d.split('-');
		var m = (a[1] * 1) - 1;
		return a[0]+'-'+m+'-'+(a[2]*1);
	}

	// function to turn a scalendar date in to a proper mysql format date
	function scalendar_proper_date ( b ) {
		var m = (b.getMonth() * 1) + 1;
		return b.getFullYear()+'-'+number_2_digits(m)+'-'+number_2_digits(b.getDate());
	}

	// function to turn a scalendar date in to a human readable date
	function scalendar_display_date ( b ) {
		var e = b.getDate() + '';
		var n = e.substr(e.length-1,1);
		if (b.getDate() > 10 && b.getDate() < 20) {
			e += 'th';
		} else if (n == '1') {
			e += 'st';
		} else if (n == '2') {
			e += 'nd';
		} else if (n == '3') {
			e += 'rd';
		} else {
			e += 'th';
		}
		return _scalendar_full_days[b.getDay()]+' '+e+' '+_scalendar_short_months[b.getMonth()];
	}

	// function to prepend 0 if needs be
	function number_2_digits ( n ) {
		n = n + '';
		if (n.length < 2) {
			return '0'+n;
		}
		return n;
	}


	// array functions
	function array_key_exists ( key, arr ) {
		for (var i in arr) {
			if (i == key) { return true; }
		}
		return false;
	}
	function array_in_array ( val, arr ) {
		for (var i in arr) {
			if (arr[i] == val) { return i; }
		}
		return -1;
	}



