

/**
 * Twit
 *  jQuery Plugin to Display Twitter Tweets on a Blog.
 *  http://code.google.com/p/jquery-twit/
 *
 * Copyright (c) 2009 Yusuke Horie
 *
 * Released under the MIT License:
 * http://www.opensource.org/licenses/mit-license.php
 *
 * Since  : 0.1.0 - 08/26/2009
 * Version: 0.1.0 - 08/26/2009
 */
(function(jQuery){var _i=0;jQuery.fn.twit=function(user,options){if(typeof user!='string')return this;var opts=jQuery.extend({},jQuery.fn.twit.defaults,options),c=jQuery.isFunction(opts.callback)?opts.callback:_callback,url='',params={};opts.user=user;url='http://twitter.com/statuses/user_timeline/'+opts.user+'.json';params.count=opts.count;return this.each(function(i,e){var $e=$(e);if(!$e.hasClass('twit'))$e.addClass('twit');jQuery.ajax({url:url,data:params,dataType:'jsonp',success:function(o){c.apply(this,[(o.results)?o.results:o,e,opts])}})})};jQuery.fn.twit.defaults={user:null,callback:null,icon:true,username:true,text:true,count:200,limit:7,label:'Twitter',title:''};var _callback=function(o,e,opts){var $this=$(e);if(!o||o.length==0||$this.length==0)return false;$this.data('_inc',1);_i++;var username=o[0].user.screen_name,icon=o[0].user.profile_image_url;var h='<div class="twitHeader">'+' <span class="twitLabel">'+opts.label+'</span>&nbsp;&nbsp;'+' <span class="twitTitle">'+opts.title+'</span>'+'</div>';if(opts.icon||opts.username){h+='<div class="twitUser">';if(opts.icon)h+=' <a href="http://twitter.com/'+username+'/">'+'  <img src="'+icon+'" alt="'+username+'" title="'+username+'" style="vertical-align:middle;" />'+' </a>&nbsp;&nbsp;';if(opts.username)h+='<a href="http://twitter.com/'+username+'/">'+username+'</a>';h+='</div>'}h+='<ul class="twitBody" id="twitList'+_i+'">'+_build(o,$this,opts)+'</ul>';$this.html(h);$('#twitList'+_i+' a.twitEntryShow').live('click.twitEntryShow'+_i,function(event){event.preventDefault();var $t=$(this);$t.parent().fadeOut(400,function(){var i=$this.data('_inc');i++;$this.data('_inc',i);if($t.hasClass('twitEntryAll')){$t.die('click.twitEntryShow'+_i);var start=(i*opts.limit)-opts.limit;$(this).after(_build(o,$this,opts,start,o.length)).remove()}else{$(this).after(_build(o,$this,opts)).remove()}})})};var _build=function(o,$t,opts,s,e){var h='',inc=$t.data('_inc'),start=s||(inc*opts.limit)-opts.limit,end=e||((o.length>start+opts.limit)?start+opts.limit:o.length);for(var i=start;i<end;i++){var t=o[i],username=t.user.screen_name,icon=t.user.profile_image_url;h+='<li class="twitEntry">';if(opts.text){var text=t.text.replace(/(https?:\/\/[-_.!~*\'()a-zA-Z0-9;\/?:\@&=+\$,%#]+)/,function(u){var shortUrl=(u.length>30)?u.substr(0,30)+'...':u;return'<a href="'+u+'">'+shortUrl+'</a>'}).replace(/@([a-zA-Z_]+)/g,'@<a href="http://twitter.com/$1">$1</a>').replace(/(?:^|\s)#([^\s\.\+:!]+)/g,function(a,u){return' <a href="http://twitter.com/search?q='+encodeURIComponent(u)+'">#'+u+'</a>'});h+=' <span>'+text+'</span>'}h+='</li>'}if(o.length>end){h+='<li class="twitNavi">'+'<a href="#" class="twitEntryShow">more</a> &nbsp;/&nbsp;';if(o.length>opts.limit)h+='<a href="#" class="twitEntryShow twitEntryAll">all</a>';h+='</li>'}return h}})(jQuery);



// http://bit.ly/ishiv | WTFPL License
window.innerShiv=function(){function h(c,e,b){return/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i.test(b)?c:e+"></"+b+">"}var c,e=document,j,g="abbr article aside audio canvas datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video".split(" ");return function(d,i){if(!c&&(c=e.createElement("div"),c.innerHTML="<nav></nav>",j=c.childNodes.length!==1)){for(var b=e.createDocumentFragment(),f=g.length;f--;)b.createElement(g[f]);b.appendChild(c)}d=d.replace(/^\s\s*/,"").replace(/\s\s*$/,"").replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,"").replace(/(<([\w:]+)[^>]*?)\/>/g,h);c.innerHTML=(b=d.match(/^<(tbody|tr|td|col|colgroup|thead|tfoot)/i))?"<table>"+d+"</table>":d;b=b?c.getElementsByTagName(b[1])[0].parentNode:c;if(i===!1)return b.childNodes;for(var f=e.createDocumentFragment(),k=b.childNodes.length;k--;)f.appendChild(b.firstChild);return f}}();

/*!
 * sfCalendar
 *
 * @version: 1.7
 * @author SimpleFlame http://www.simpleflame.com/
 *
 * Other settings:
 *  months       - labels for month names
 *  monthsShort  - shortname labels for month names
 *  days         - labels for day names
 *  daysShort    - shortname labels for day names
 *  listWrapper   - wrapper for the aside content column 
 *  calWrapper   - wrapper for the aside content column 
 *  tagsWrapper  - wrapper for the aside content column 
 *  tagsList     - custom element with tags
 *  defaultView  - 'today'
 *  tagsWidget    - list or select, default list
 */ 
(function($){

	var sfCalendar = function(el){
		this.$root = $(el);

		this.settings = {
			'months'      : ['January','February','March','April','May','June','July','August','September','October','November','December'],
			'monthsShort' : ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'],
			'days'        : ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'],
			'daysShort'   : ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'],
			'defaultView' : 'today',
			'dataItem'    : '.data .item',
			'tagsWidget'  : 'list',
			'tagsList'    : null
		};


		var options = arguments[1] || {};
		this.settings = $.extend(this.settings, options);

		this.items = this.parseData();

		this.structure();	
		
		this.init();
	};

	/*
	 * In order to compare dates we have to make sure that values match to to the millisecond,
	 * so every date has to be normalized.
	 * You can pass true as the second parameter to set to the end of the day
	 */
	sfCalendar.prototype.normalizeDate = function(date){
		if (!arguments[1]) {
			date.setHours(0);
			date.setMinutes(0);
			date.setSeconds(0);					
			date.setMilliseconds(0);		
		}
		else { //end of the day
			date.setHours(23);
			date.setMinutes(59);			
			date.setSeconds(59);			
			date.setMilliseconds(999);						
		}
		
		return date;
	};

	/*
	 * General structure of calendar listing
	 */
	sfCalendar.prototype.structure = function(){

		this.$period = $('<h3 class="sfcalendar-widget-period"/>');		
		this.$root.append(this.$period);
			
		//events listing	
		var list = this.listWidget();	
		if (this.settings.listWrapper) {
			$(this.settings.listWrapper).append(list);
		}
		else {
			this.$root.append(list);
		}
		
		//calendar		
		var cal = this.calWidget();		
		if (this.settings.calWrapper) {
			$(this.settings.calWrapper).append(cal);
		}
		else {
			this.$root.append(cal);
		}
		
		//tags
		if (this.settings.tagsList) { //custom tags listing
			this.$tags = $(this.settings.tagsList);
			this.tagsListWidgetAddEvents(this.$tags);
		}
		else {			
			var tags = this.tagsWidget();
			
			if (this.settings.tagsWrapper) { //custom tags wrapper
				$(this.settings.tagsWrapper).append(tags);
			}
			else {
				this.$root.append(tags);
			}					
		}
	};

	/*
	 * Explodes a comma separated string into an array of trimmed strings
	 */
	sfCalendar.prototype.parseTags = function(str){
		var tags = str.split(',');
		return $.map(tags,function(tag){
			tag = $.trim(tag); //removes whitespace
			return tag ? tag : null; //removes empty tags
		});
	};

	/*
	 * Reads events data from html
	 */
	sfCalendar.prototype.parseData = function(){
		var 
			items = [],
			self = this,
			tags = [];

		var monthIndexes = {};	
		$.each(this.settings.monthsShort,function(index, item){
			monthIndexes[item] = index;
		});	

		this.$root.find('div.data div.item').each(function(eventIndex, item){

			var 
				startDateArr, startDate, eventDates, endDate, endDateArr, startTime, endTime, 
				oneDayMilliseconds,diffDays, tDate, i,
				location = $.trim($(this).find('.location').text()),
				itemTags = self.parseTags($(this).find('.tags').text()),
				description = $(this).find('.description').html(),
				time = $(this).find('.time').html(),
				title = $(this).find('.title').html(),
				thumb = $(this).find('.thumbnail').html(),
				register = $(this).find('.register').html(),
				duration = $(this).find('.duration').html();
				
			//append item tags to global array
			$.each(itemTags, function(index, item){
				if ($.inArray(item, tags) === -1) {
					tags[tags.length] = item;					
				}
			});

			startDateArr = $(this).find('.date .start').text().split('-');
			startDate = new Date();			
			startDate.setFullYear(startDateArr[2], monthIndexes[startDateArr[1]], startDateArr[0]);
			startDate = self.normalizeDate(startDate);

			eventDates = [startDate];

			endDate = null;

			if ($(this).find('.date .end').length > 0 && $.trim($(this).find('.date .end').text()) !== '') {
				endDateArr = $(this).find('.date .end').text().split('-');
				endDate = new Date();			
				endDate.setFullYear(endDateArr[2], monthIndexes[endDateArr[1]], endDateArr[0]);
				endDate = self.normalizeDate(endDate);				

				startTime = startDate.getTime();
				endTime = endDate.getTime();
				oneDayMilliseconds = 60*60*24*1000;				
				diffDays = (endTime - startTime)/oneDayMilliseconds;

				for (i = 1; i <= diffDays; i++){
					tDate = new Date();					
					tDate.setTime(startTime + i * oneDayMilliseconds);
					tDate.setTime(tDate.getTime() - (startDate.getTimezoneOffset() - tDate.getTimezoneOffset()) * 60000);					
					eventDates[eventDates.length] = tDate;
				}

			}

			$.each(eventDates,function(index, date){
				var event = {
					id : eventIndex, //unique id for add - simply index in the array of all events  
					description : description,
					location : location,
					time : time,
					tags : itemTags,
					date : date,
					startDate : startDate,
					endDate : endDate,
					title : title,
					thumb : thumb,
					duration : duration,
					register : register
				};			

				items[items.length] = event;				
			});

		});	

		this.tags = tags;
		this.activeTags = [];

		//we no longer need data list
		this.$root.find('div.data').remove();

		//sort items by date
		items.sort(function(a,b){
			if (a.date < b.date) {
				return -1;
			}
			if (a.date > b.date) {
				return 1;
			}
			return 0;
		});

		return items;
	};

	/* 
	 * Basically checks if any item tag is in the array of currently active tabs
	 */
	sfCalendar.prototype.isEventInActiveTags = function(item) {
		if (this.activeTags.length === 0) {
			return true;
		}

		var 
			self = this,
			flag = false;

		$.each(item.tags, function(index, tag){
			if ($.inArray(tag, self.activeTags) > -1) {
				flag = true;
				return false; //break out from the loop
			}
		});

		return flag;
	};

	/*
	 * Filters item set to return only these from a given month
	 */
	sfCalendar.prototype.fetchEventsForMonth = function(date){
		var 
			self = this,
			month = date.getMonth(),
			year = date.getFullYear();

		return $.grep(this.items, function(item){
			if (self.isEventInActiveTags(item) === false) {
				return false;
			}
			return (item.date.getMonth() === month && item.date.getFullYear() === year);
		});
	};

	/* 
	 * Return events for a particular day
	 */	
	sfCalendar.prototype.fetchEventsForDay = function(date){
		var 
			self = this,
			month = date.getMonth(),
			year = date.getFullYear(),
			day = date.getDate();

		return $.grep(this.items, function(item){
			if (self.isEventInActiveTags(item) === false) {
				return false;
			}			
			return (item.date.getMonth() === month && item.date.getFullYear() === year && item.date.getDate() === day);
		});
	};

	/*
	 * Returns all events between a particular date
	 */
	sfCalendar.prototype.fetchEventsForPeriod = function(startDate, endDate){
		var 
			self = this;

		startDate = this.normalizeDate(startDate);
		endDate = this.normalizeDate(endDate, true); //second parameter this will set at the very last moment of the day		

		return $.grep(this.items, function(item){
			if (self.isEventInActiveTags(item) === false) {
				return false;
			}			
			return (item.date.valueOf() >= startDate.valueOf() && item.date.valueOf() <= endDate.valueOf());
		});
	};


	sfCalendar.prototype.removeNavigation = function(){
		this.$root.find('p.sfcalendar-widget-nav').unbind('click').remove();
	};
	/**
	 * Builds month navigation
	 */
	sfCalendar.prototype.navWidget = function(){
		var 
			nav = $('<p class="sfcalendar-widget-nav" />'),
			months = this.settings.months,
			startDate = arguments[0] || new Date();			

		//tabs
		nav.click($.proxy(function(e){
			if (e.target.nodeName.toLowerCase() !== 'a') {
				return true;
			}

			e.preventDefault();
			var date = $(e.target).data('date');		
			
			//rebuild tabs with new Date as a starter						
			this.rebuildCalendar(date);
			this.repopulateCalendar(date);			

			//reactive current selection
			var event = this.$cal.data('selection');			
			$(document).trigger(event.type, event.data);
			$(document).trigger('setmonth.sfcalendar', [date]);
		},this));

		//builds previous and next links 
		var createLink = function(offset, className){
			var
				newDate = new Date(),
				newMonth = startDate.getMonth() + offset,
				newYear = startDate.getFullYear();

			if (newMonth < 0) {
				newMonth = newMonth + 12;
				newYear = newYear - 1;
			}
			//next year
			else if (newMonth > 11){
				newMonth = newMonth - 12;
				newYear = newYear + 1;
			}				

			newDate.setFullYear(newYear,newMonth,1);
			return $('<a href="#" class="' + className + '">' + months[newMonth] + '</a>').data('date',newDate);
		};

		var 
			$prev = createLink(-1, 'prev'),
			$next = createLink(1, 'next');

		nav.append($prev, document.createTextNode(' '+months[startDate.getMonth()]+' '+startDate.getFullYear()), $next);			

		return nav;
	};

	/* 
	 * Initializes listing 
	 */
	sfCalendar.prototype.listWidget = function(){
		var 
			self = this,
			widget = $('<div class="sfcalendar-widget-list" />');
		
		var updateListing = function(dataItems) {
			var 
				days = self.settings.days,
				months = self.settings.months;

			widget.empty(); //remove previous items

			//no results for given month
			if (dataItems.length === 0) {
				widget.append('<p class="empty">No events to show</p>');
				return;
			}

			var previousDate = null;

			$.each(dataItems, function(index, item){


				var el = $('<div class="section-a day"/>');

				//title
				if (item.title) {
					el.append('<h2 class="a">'+ item.title + '</h2>');
				}
				
				var desc = $('<div/>');
				
				var day = item.date.getDate();

				if (day < 10) {
					day = '0'+day;
				}
								
				desc.append('<p class="date">Class Starts: '+ months[item.date.getMonth()]+' ' + day + ', ' + item.date.getFullYear() );
				
				if (item.duration) {
					desc.append('<p class="time">' + item.duration + '</p>');
				}
																
				desc.append(item.description);
				
				if (item.register) {
					desc.append('<p><a href="' + item.register + '" class="btn-a"><span>Register online</span></a></p>');
				}				
				
				el.append(desc);
								
				if (item.thumb) {

					el.append($(item.thumb).addClass('photo-a right'));					
				}
				
				if (item.endDate !== null){
					el.find('h2').after('<p class="dates">' + self.settings.months[item.startDate.getMonth()] + ' ' + item.startDate.getDate() + ', ' + item.startDate.getFullYear() + ' to ' + self.settings.months[item.endDate.getMonth()] + ' ' + item.endDate.getDate() + ', ' + item.endDate.getFullYear() + '</p>');
				}

				widget.append(el);
			});			
		};

		//update listing when date is change in the calendar
		$(document).bind('setday.sfcalendar', $.proxy(function(event,date){
			this.$period.html('<span>Day:</span> ' + this.settings.months[date.getMonth()] + ' ' + date.getDate() + ', ' + date.getFullYear());
			updateListing(this.fetchEventsForDay(date));
		},this));

		$(document).bind('setmonth.sfcalendar', $.proxy(function(event,date){
			this.$period.html('<span>Month:</span> ' + this.settings.months[date.getMonth()] + ' ' + date.getFullYear());			
			updateListing(this.fetchEventsForMonth(date));
		},this));

		$(document).bind('setweek.sfcalendar', $.proxy(function(event,startDate,endDate){
			this.$period.html('<span>Week:</span> ' + this.settings.months[startDate.getMonth()] + ' ' + startDate.getDate() + ' - '+ self.settings.months[endDate.getMonth()] + ' ' + endDate.getDate() + ', ' + startDate.getFullYear());						
			updateListing(this.fetchEventsForPeriod(startDate,endDate));
		},this));		
		
		this.$list = widget;
		
		return widget;				
	};

	/*
	 * Tags filter list
	 */
	sfCalendar.prototype.tagsWidget = function(){
		if (this.settings.tagsWidget === 'select') {
			return this.tagsSelectWidget();
		}
		return this.tagsListWidget();
	};
	
	sfCalendar.prototype.tagsListWidget = function(){
		var widget = $('<ul class="sfcalendar-widget-tags" />');		

		$.each(this.tags, function(index, item){
			var
				$li = $('<li><label for="sfcalendar-tag-'+index+'"> '+item+'</label></li>'),
				$checkbox = $('<input type="checkbox" id="sfcalendar-tag-'+index+'" value="'+item+'"/>');

			$li.find('label').prepend($checkbox);
			widget.append($li);
		});

		this.tagsListWidgetAddEvents(widget);
		this.$tags = widget;
		
		return widget;
	};
	
	sfCalendar.prototype.tagsListWidgetAddEvents = function(widget){
		widget.find('input[type="checkbox"]').click($.proxy(function(e){
			var data = [];

			widget.find('input:checked').each(function(){
				data[data.length] = $(this).val();
			});

			this.activeTags = data;

			//update calendar widget
			this.repopulateCalendar(this.$cal.data('date'));
			
			var event = this.$cal.data('selection');			
			$(document).trigger(event.type, event.data);						
		},this));		
		
		this.$tags = widget;
		
		return widget;
	};
	
	sfCalendar.prototype.tagsSelectWidget = function(){
		var 
			widget = $('<p class="sfcalendar-widget-tags"><label for="sfcalendar-tag">Refine by Event Type</label> <select id="sfcalendar-tag" name="sfcalendar-tag"><option/></select>'),
			select = widget.find('select');

		$.each(this.tags, function(index, item){
			select.append('<option value="'+item+'">'+item+'</option>');
		});

		this.tagsSelectWidgetAddEvents(widget);
		return widget;		
	};
		
	sfCalendar.prototype.tagsSelectWidgetAddEvents = function(widget){
		widget.find('select').change($.proxy(function(e){
			var val = $(e.target).val();

			this.activeTags = [];
			if (val) {
				this.activeTags = [val];
			}
			
			//update calendar widget
			this.repopulateCalendar(this.$cal.data('date'));
			
			var event = this.$cal.data('selection');			
			$(document).trigger(event.type, event.data);						
		},this));		
		
		return widget;		
	};
	
	/*
	 * Builds calendar widget
	 */
	sfCalendar.prototype.calWidget = function(){
		var 
			widget = $('<div class="sfcalendar-widget-cal"/>');

		//catches clicks on the whole calendar widget
		widget.click(function(e){
			if (e.target.nodeName.toLowerCase() !== 'a') {
				return;
			}

			//omit navigation links
			if ($(e.target).hasClass('prev') || $(e.target).hasClass('next')) {
				return true;
			}
			
			e.preventDefault();

			var $target = $(e.target);

			//month cell click
			if ($target.hasClass('month')) {
				$(document).trigger('setmonth.sfcalendar',[$target.data('date')]);
			}
			//week cell click
			else if ($target.hasClass('week')) {
				$(document).trigger('setweek.sfcalendar',[$target.data('date.start'), $target.data('date.end')]);
			}
			//day cell click
			else {
				$(document).trigger('setday.sfcalendar',[$target.data('date')]);
			}
		});

		//selecting whole month
		$(document).bind('setmonth.sfcalendar',$.proxy(function(event, date){	
			date = this.normalizeDate(date);

			widget.data('selection',{
				'type' : 'setmonth.sfcalendar',
				'data' : [date]
			});						

			if (date.valueOf() === widget.data('date').valueOf()) {
				widget.find('td a').addClass('selected');
			}
		},this));

		//selecting only one week
		$(document).bind('setweek.sfcalendar', function(event, startDate, finishDate){
			widget.data('selection',{
				'type' : 'setweek.sfcalendar',
				'data' : [startDate, finishDate]
			});			

			widget.find('td a').removeClass('selected');

			widget.find('tbody th a').each(function(){
				if ($(this).data('date.start').valueOf() === startDate.valueOf()) {
					$(this).parents('tr').find('td a').addClass('selected');
				}
			});
		});		

		//selecting a particular day
		$(document).bind('setday.sfcalendar', function(event, date){

			widget.data('selection',{
				'type' : 'setday.sfcalendar',
				'data' : [date]
			});

			widget.find('td a').removeClass('selected');

			widget.find('tbody td a').each(function(){
				if ($(this).data('date').valueOf() === date.valueOf()) {
					$(this).addClass('selected');
				}
			});
		});

		this.$cal = widget;

		var now = new Date();

		this.rebuildCalendar(now);
		this.repopulateCalendar(now);
		
		return widget;
	};

	/*
	 * Fetches events for current month and marks them in the calendar
	 */
	sfCalendar.prototype.repopulateCalendar = function(date){
		var 
			tdate, weekday,
			dataItems = this.fetchEventsForMonth(date);

		tdate = date;
		tdate.setDate(1);
		weekday = tdate.getDay();

		this.$cal.find('a.event').removeClass('event');

		$.each(dataItems, $.proxy(function(index, item){
			var day = item.date.getDate() + weekday - 1; //we add weekday as it's the offset at the beginning of the calendar
			this.$cal.find('td').eq(day).find('a').addClass('event');
		},this));						
	};

	/*
	 * Creates HTML for calendar widget
	 */ 
	sfCalendar.prototype.rebuildCalendar = function(date){

		
		
		date.setDate(1); //reset to the first day of passed month
		date = this.normalizeDate(date);

		var 
			weekday, rows, $row, $cell, $trigger, daysLimit, dayDate,
			firstDayOfMonth,
			i,j,
			counter = 0,
			displayedDay = 1,
			daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31],

			$table = $('<table summary="Calendar for ' + parseInt(date.getMonth() + 1, 10) + '.'+ date.getFullYear() +'"><thead/><tbody/></table>'),
			selectWeekStartDate, selectWeekEndDate;

		//cleanup
		this.removeNavigation(); //remove 
		this.$cal.empty(); //remove previous items
		
		this.$cal.data('date',date);
		this.$cal.prepend(this.navWidget(date));				

		if (date.getFullYear() % 4 === 0) {
			daysInMonth[1] = 29;
		}

		//weekday of the first day of current month
		weekday = date.getDay();
		daysLimit = daysInMonth[date.getMonth()] + weekday;
		rows = Math.ceil(daysLimit / 7);

		//header row
		$row = $('<tr />');
		$trigger = $('<a href="#" class="month">M</a>').data('date',date); //month changing trigger
		$cell = $('<th scope="col"/>');
		$row.append($cell.append($trigger));

		//day names
		$.each(this.settings.daysShort, function(){
			$row.append('<th scope="col">'+this+'</th>');
		});

		$table.find('thead').append($row);

		firstDayOfMonth = false;

		for (i = 0; i < rows; i++) {
			//week selecting row
			$row = $('<tr />');

			//cells
			for (j = 0; j < 7; j++) {
				$cell = $('<td class="col' + parseInt(j+1,10) + '"/>');

				//existing day in month
				if (counter >= weekday && counter < daysLimit) {

					dayDate = new Date(date.getFullYear(),date.getMonth(),displayedDay,0,0,0);

					//look for the first day in month/week
					if (firstDayOfMonth === false || j === 0) {
						selectWeekStartDate = dayDate;
					}
					firstDayOfMonth = true;

					//look for the last day of the week
					if (j === 6 || counter + 1 === daysLimit) { 
						selectWeekEndDate = dayDate;
					}

					$trigger = $('<a href="#">'+ displayedDay +'</a>').data('date', dayDate);
					$cell.append($trigger);
					displayedDay++;
				}
				else {
					$cell.html('&nbsp;');
				}

				counter++;
				$row.append($cell);
			}

			//week selection trigger			
			$cell = $('<th scope="row"/>');
			$trigger = $('<a href="#" class="week">W</a>').data('date.start',selectWeekStartDate).data('date.end',selectWeekEndDate);			
			$row.prepend($cell.append($trigger));

			$table.find('tbody').append($row);
		}

		this.$cal.append($table);
	};

	sfCalendar.prototype.init = function(){
		
		var now = this.normalizeDate(new Date());					
		
		//active today's date
		switch (this.settings.defaultView) {
			case 'month':
				now.setDate(1);
				$(document).trigger('setmonth.sfcalendar',[ now ]);
			break;
			default:
				$(document).trigger('setday.sfcalendar',[ now ]);				
			break;				
		}
		
	};
	
	$.fn.sfCalendar = function(options){
		return $(this).each(function(){
			return new sfCalendar(this,options);
		});
	};

}(jQuery));

/*!
 * (v) Compact labels plugin (v20110124)
 * Takes one option: labelOpacity [default: true] set to false to disable label opacity change on empty input focus
 */
(function($){$.fn.compactize=function(options){var defaults={labelOpacity:true};options=$.extend(defaults,options);return this.each(function(){var label=$(this),input=$('#'+label.attr('for'));input.focus(function(){if(options.labelOpacity){if(input.val()===''){label.css('opacity','0.5');}}else{label.hide();}});input.keydown(function(){label.hide();});input.blur(function(){if(input.val()===''){label.show();if(options.labelOpacity){label.css('opacity',1);}}});window.setTimeout(function(){if(input.val()!==''){label.hide();}},50);});};})(jQuery);

/**
 * SimpleFlame Content rotator
 * Version 1.0
 *
 * Available effects:
 *  - if UI effects have been added: 'blind', 'bounce', 'clip', 'drop', 'explode', 'fold', 'highlight', 'puff', 'pulsate', 'scale', 'shake', 'size', 'slide', 'transfer'
 *  - basic effects from $: fadeIn, fadeOut, show, hide, slideUp, slideDown
 * 
 * Settings:
 *  - item : selector for rotator item ( default : 'li' )
 *  - activeClass : active item indicator ( default : 'active' )
 *  - duration : duration cycle in miliseconds ( default : 5000 )
 *  - autorotate : bool ( default: true )
 *  - effectIn : effect triggered on showing new item  (default: fadeIn)
 *  - optionsIn : additional options used in show transitio (default: { })
 *  - speedIn' : effectIn speed	( default : normal )
 *  - effectOut' : effect triggered on hiding old item ( default : fadeOut )
 *  - optionsOut' : additional options used in hide transition ( default : {} )
 *  - speedOut' : effectOut speed ( default : normal )
 *  - random : bool - should items be randomized on page load ( default : false )
 */
eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('(6($){6 11(g){4 i=g.Z;8(i===0){S w}1m(--i){4 j=1e.1k(1e.H()*(i+1));4 1i=g[i];4 1g=g[j];g[i]=1g;g[j]=1i}}4 9=6(V,h){2.3={\'d\':\'L\',\'c\':\'O\',\'12\':1y,\'p\':m,\'q\':\'1t\',\'1d\':{},\'D\':\'W\',\'u\':\'1s\',\'15\':{},\'I\':\'W\',\'H\':w};$.1r(2.3,h);2.$b=$(V);2.Y()};9.l.Y=6(){2.$b.s(\'z-7\');2.$A=$(\'<1v 17="z-1w" />\');2.$b.1z(2.$A);2.$A.C(2.$b);2.$v=$(\'<1q 17="z-v" />\');2.$A.C(2.$v);2.$7=2.$b.1x(2.3.d);8(2.3.H===m){2.$7=2.$7.1A();11(2.$7);2.$b.C(2.$7)}2.$e=2.$7.B(2.$7.1p(\'.\'+2.3.c));8(2.$e<0){2.$e=0}4 5=2;2.$7.s(\'z-d\').16(6(B,d){4 t=$(\'<L><a 1n="#">\'+1o(B+1,10)+\'</a></L>\');5.$v.C(t);t.1f(\'a\').F(\'d\',d).1G(\'1S\',{5:5},5.t)});2.x(2.$e,m);8(2.3.p){2.p()}};9.l.t=6(J){J.1U();4 5=J.F.5;5.T();5.$U=m;4 n=5.$7.B($(2).F(\'d\'));5.x(n)};9.l.x=6(n){4 18=1B[1]||w;4 c=2.3.c;4 k=2.$7.Q(2.$e);4 f=2.$7.Q(n);4 N=6(){k.R(c)};4 E=6(){f.s(c).1j(\'1h\',10)};4 M=[\'1Q\',\'1V\',\'1X\',\'1Y\',\'1W\',\'1R\',\'1O\',\'1P\',\'1F\',\'1E\',\'1C\',\'1D\',\'1H\',\'1I\'];8(18===m){k.R(c).K();f.s(c).G()}o{8($.19(2.3.u,M)>-1){k.K(2.3.u,2.3.15,2.3.I,N)}o 8($.1a(k[2.3.u])){k[2.3.u](2.3.I,N)}o{1c"1b K 14"}f.1j(\'1h\',1L);8($.19(2.3.q,M)>-1){f.G(2.3.q,2.3.1d,2.3.D,E)}o 8($.1a(f[2.3.q])){f[2.3.q](2.3.D,E)}o{1c"1b G 14"}}2.$v.1f(\'a\').R(\'O\').Q(n).s(\'O\');2.$e=n};9.l.p=6(){2.$U=w;4 5=2;2.$b.1K(6(){5.T()});2.$b.1J(6(){5.P()});2.P()};9.l.P=6(){8(2.$U===m){S}4 5=2;2.$X=13.1N(6(){4 y=5.$e+1;8(y===5.$7.Z){y=0}5.x(y)},2.3.12)};9.l.T=6(){8(2.3.p){13.1T(2.$X)}};$.1l.9=6(h){h=h||{};S 2.16(6(){4 r=1u 9(2,h)})}})(1M);',62,123,'||this|settings|var|self|function|items|if|sfRotator||container|activeClass|item|current|newItem|myArray|options|||oldItem|prototype|true|position|else|autorotate|effectIn||addClass|trigger|effectOut|controls|false|activate|next|sf|wrapper|index|append|speedIn|onShow|data|show|random|speedOut|event|hide|li|effects|onHide|active|startAutorotate|eq|removeClass|return|stopAutorotate|rotationTerminated|el|normal|rotationInterval|build|length||fisherYates|duration|window|transition|optionsOut|each|class|instant|inArray|isFunction|Unsupported|throw|optionsIn|Math|find|tempj|zIndex|tempi|css|floor|fn|while|href|parseInt|filter|ul|extend|fadeOut|fadeIn|new|div|rotator|children|5000|before|detach|arguments|shake|size|scale|pulsate|bind|slide|transfer|mouseleave|mouseenter|100|jQuery|setInterval|highlight|puff|blind|fold|click|clearInterval|preventDefault|bounce|explode|clip|drop'.split('|'),0,{}));

/*!
 * Scripts
 *
 */
jQuery(function($) {
 
	var Engine = {
		utils : {
			links : function(){
				$('a[rel*="external"]').click(function(e){
					e.preventDefault();
					window.open($(this).attr('href'));
				});
			},
			mails : function(){
				$('a[href^="mailto:"]').each(function(){
					var mail = $(this).attr('href').replace('mailto:','');
					var replaced = mail.replace('/at/','@');
					$(this).attr('href','mailto:'+replaced);
					if($(this).text() === mail) {
						$(this).text(replaced);
					}
				});
			}
		},
		
		enhancements : {
			newsletter : function() {
				var form = $('.newsletter'),
					toggle = $('h2', form),
					offset = form.outerWidth() - 52;
					
				var showNewsletter = function() {
						form.removeClass('hidden');
						form.animate({ right: 0 }, 500);
					},
					hideNewsletter = function() {
						form.animate({ right: -offset }, 500, function() {
							$(this).addClass('hidden');
						});
					}

				toggle.click(function(){
					if(form.is('.hidden')) {
						showNewsletter();
					} else {
						hideNewsletter();
					}
				
					return false;
				});
				
				$('body').click(function(e){
					if(!form.is('.hidden')) {
						if(!$(e.target).is('.newsletter') && !$(e.target).closest('.newsletter').length) {
							hideNewsletter();
						}
					}
				});
				
				$('label', form).compactize();
			},
			
			rotator : function() {
				$('.rotator-a > ul').sfRotator();
			}
		},
		
		fixes : {
			enhancements : function() {
				if($.browser.msie && parseInt($.browser.version,10) < 9){
					$(':last-child:not(cufon)').addClass('last-child');
				}
			}
		},
		ui : {
			calendar : function(){
				$('#events-a').sfCalendar({
					label : 'Class Calendar',
					defaultView : 'month',
					listWrapper : '#calendar-list',
					calWrapper : '#calendar-cal',
					tagsWrapper : '#calendar-tags'
				});
			}
		},
		
		tweaks : {
				
				
						tweets : function(){
						  if ($('#tweets').size() === 0) { return;}
					   
							 $('#tweets').twit('adobebc', {
							   limit: 5,
							   icon: false
							 });
							
						}, // tweets
						
						
						bookings : function(){
							// check calendar webapp item for booking link
							// if none kill register button
							if(jQuery("div.day").length > 0){
								jQuery("div.day a.btn-a").each(function(){
									if(jQuery(this).attr("href") == ""){
										jQuery(this).hide();
									}
								});
							}
							
						}, // bookings
						
						fancyGallery : function(){
                        
                        
                         if(jQuery("td.photogalleryItem").length > 0){
                   
                              jQuery("td.photogalleryItem").each(function(){
                                   if(jQuery(this).find("a").length > 0 )     {                                        var link = jQuery(this).find("a").attr("href");
                                        var img = jQuery(this).find("img").attr("src");
                                        jQuery(this).html("<a href='"+link+"' class='fancybox' rel='Gallery'><img src='"+img+"'></a>");
                                   }
                                  
                              });
                          }
                        
						if(jQuery("a.fancybox").length > 0){
						
                         jQuery("a.fancybox").fancybox({
								'transitionIn'	: 'elastic',
								'transitionOut'	: 'elastic'
							});
						}
                        
                    } // fancyGallery
						
						
					
							
				
		}// tweaks
	};


	Engine.utils.links();
	Engine.utils.mails();
	Engine.ui.calendar();
	Engine.enhancements.newsletter();
	Engine.enhancements.rotator();
	Engine.fixes.enhancements();
	
	Engine.tweaks.tweets();
	
	Engine.tweaks.bookings();
	
	Engine.tweaks.fancyGallery();

	
});
