/**
 * @classDescription Calendar Overlay object
 * @author Jeremy.Manoto
 */

	var calendarService = VirtualDirectory + "/services/ProductionCalendar.ashx"

	var calendarOverlay;
	var calendarHasFilter;
	var calendarCategory;
	var calendarLocation;
	function CalendarOverlay_Init(){
		$(document).ready(function() {
			$(function() {
				calendarOverlay = $("a.trigger-calendar").overlay({

					expose: {
						color: '#000000',
						opacity: 0.7,
						closeSpeed: 1000
					},
					onBeforeLoad: function() {

						$("div.VimeoHolder").css({ "height": "308px" });
						$("div.VimeoHolderInner").css({ "display": "none" });


						var trigger = this.getTrigger();
						calendarCategory = $(trigger).find("span[title='series']").html();
						calendarLocation = $(trigger).find("span[title='location']").html();

						calendarHasFilter = (calendarCategory != "" && calendarLocation != "");

						LoadFilters(calendarCategory, calendarLocation);
					},

					onClose: function() {
						$("div.VimeoHolder").css({ "height": "308px" });
						$("div.VimeoHolderInner").css({ "display": "block" });
					},
					onLoad: function() {

						//Find out what's loaded first!!! before requesting more data (otherwise DUPLICATES!)

						calendar.filterCategory = calendarCategory;
						calendar.filterLocation = calendarLocation;

						//Google Analytics Virtual Page Tracking
						var selectedcategory = $(".filter.category option:selected").html();
						if (calendar.calendarHasFilter) {
							_gaq.push(['_trackPageview', '/whatson/' + selectedcategory + '/' + calendar.calendarLocation]);
						} else {
							if (calendar.calendarCategory != "" && !calendar.calendarCategory) {
								_gaq.push(['_trackPageview', '/whatson/' + selectedcategory]);
							}
							else if (calendar.calendarLocation != "") {
								_gaq.push(['_trackPageview', '/whatson/All-Series/' + calendar.calendarLocation]);
							}
							else {
								_gaq.push(['_trackPageview', '/whatson']);
							}
						}
						
						calendar.updatePerformances();

						//chrisb: set default filters on cafe carnivale and national concert pages
						//and force the cal to update to reflect them
						if (window.location.pathname.indexOf("cafecarnivale") > -1) {
							$("#.filter.category option[value='3']").attr('selected', 'selected');
							$("#.filter.category option[value='3']").change();
						}
						else if (window.location.pathname.indexOf("concertseason") > -1) {
							$("#.filter.category option[value='1']").attr('selected', 'selected');
							$("#.filter.category option[value='1']").change();
						}

						/*
						if (!calendarHasFilter) {
						//Load the performances
						$.get(calendarService, { a: 'PERFORMANCES' }, function(data){
						var performances = eval(data);
						var performance;
						for (var p in performances) {
						if (performances[p].performance_id) {
						performance = new DetailItem(performances[p].performance_id, performances[p].production_title, performances[p].production_pagelink, performances[p].venue_city, performances[p].venue_title, performances[p].performance_datetime, VirtualDirectory + performances[p].image_1, performances[p].performance_book_url, performances[p].productioncategory_id, performances[p].venue_city);
						calendar.addDetailItem(performance);
						}
						}
						calendar.sortDetailItems();
						});
						} else {
						$.get(calendarService, { a: 'PERFORMANCES', c: calendarCategory, l: calendarLocation }, function(data){
						var performances = eval(data);
						var performance;
						for (var p in performances) {
						if (performances[p].performance_id) {
						performance = new DetailItem(performances[p].performance_id, performances[p].production_title, performances[p].production_pagelink, performances[p].venue_city, performances[p].venue_title, performances[p].performance_datetime, VirtualDirectory + performances[p].image_1, performances[p].performance_book_url, performances[p].productioncategory_id, performances[p].venue_city);
						calendar.addDetailItem(performance);
						}
						}
						calendar.sortDetailItems();
						});
						}*/



					},
					closeOnClick: true
				});
			});


		});
	}

	function LoadFilters(series, location) {
		//Load Categories (if not already)
		var filterCategory = $(".filter.category");

		if (filterCategory.children().length == 0) {
			filterCategory.append("<option value=''>- Series -</option>");
			$.get(calendarService, {
				a: "CATEGORIES"
			}, function(data){
				var categories = eval(data);
				
				for (var cat in categories) {
					if (categories[cat].productioncategory_id) 
						filterCategory.append("<option value='" + categories[cat].productioncategory_id + "'>" + categories[cat].productioncategory_name + "</option>")
				}
				
				// Set default value
				filterCategory.val(series);
			})
		}	
		
		var filterLocation = $(".filter.location");

		if (filterLocation.children().length == 0) {
			filterLocation.append("<option value=''>- Location -</option>")
			$.get(calendarService, { a: "LOCATIONS"}, function(data) {
				var locations = eval(data);
				
				for (var loc in locations) {
					if (locations[loc].venue_city) 
						filterLocation.append("<option value='" + locations[loc].venue_city + "'>" + locations[loc].venue_city + "</option>")
				}
				
				// Set default value
				filterLocation.val(location);
			})
		}
	}


	/**
	 * Calendar Object
	 */

	var Calendar;
	Calendar = base2.Base.extend({
		constructor: function(container) {
			this.container = $(container);
			this.sortList = this.container.find(".sort-list");
			this.filterContent = this.container.find(".filters");
			this.sortListContent = this.sortList.find(".scroll-content .scroll-wrapper");
			this.details = this.container.find(".details");
			this.detailsContent = this.details.find(".scroll-content .scroll-wrapper");

			this.detailItems = new base2.Array2();
			this.years = new base2.Array2();

			this.setScrollable();
			this.setEvents();

			this.filterCategory = "";
			this.filterLocation = "";
			this.currentMonth;
			this.currentYear;

			//chris b: build filter inputs programatically to appease google
			this.container.find(".close").append("X");
			this.filterContent.append("Filter series by: ");
			this.filterContent.append("<select id='ddlCategory' name='ddlCategory' class='filter category'></select> ");
			this.filterContent.append("<select id='ddlLocation' name='ddlLocation' class='filter location'></select>");
			this.filterContent.append("<input type='reset' class='filter-none' id='btnCalendarReset' name='btnCalendarReset' title='All series & locations' value='All series & locations'></input>");

			var outer = this;

			// Apply Reset Filter event
			this.filterContent.find(".filter-none").live("click", function() {
				outer.resetFilters();
			});

			// Apply Filter Category selections event
			this.filterContent.find(".filter.category").change(function() {
				var category = $(this).val();

				calendar.filterCategory = category;
				calendar.filterLocation = "";

				//Google Analytics Virtual Page Tracking
				var selectedcategory = $(".filter.category option:selected").html();
				if (calendar.filterCategory == "") {
					_gaq.push(['_trackPageview', '/whatson']);
				} else {
					_gaq.push(['_trackPageview', '/whatson/' + selectedcategory]);
				}

				calendar.updatePerformances();

				//todo: reset locations based on the selected category
				calendar.updateLocations();

			});

			// Apply Filter Location selections event
			this.filterContent.find(".filter.location").change(function() {
				var location = $(this).val();

				calendar.filterLocation = location;

				//Google Analytics Virtual Page Tracking
				var selectedcategory = $(".filter.category option:selected").html();
				if (calendar.filterCategory == "") {
					_gaq.push(['_trackPageview', '/whatson/All-Series/' + calendar.filterLocation]);
				} else {
					_gaq.push(['_trackPageview', '/whatson/' + selectedcategory + '/' + calendar.filterLocation]);
				}

				calendar.updatePerformances();

			})

			$("#cal_loading").show();
			$("#cal_loading").append("<img src='" + VirtualDirectory + "/images/MusicaViva/ajax-loader.gif' /> <span>Loading calendar...</span>");
		},
		getYears: function() {
			return this.sortList.find(".scroll-content .group-by");

		},
		getMonths: function() {
			return this.sortList.find(".scroll-content .item");
		},
		getDetailYears: function() {
			return this.detailsContent.find(".scroll-content .group-by");
		},
		getDetailItems: function() {
			return this.detailsContent.find(".scroll-content .item");
		},
		loadMonths: function() {
			//Queryies the array for a list of years

			var currentYear = "";
			var calendar = this;
			var container = this.container;
			var sortListContent = this.sortListContent;

			calendar.detailItems.forEach(function(item) {
				currentYear = item.date.toString("yyyy");
				var year = new SortGroup(currentYear, true);

				if (container.find("#" + year.label).length == 0) {
					//year doesn't exist
					calendar.years[calendar.years.length] = year;

					//determine where to insert the year
					var insertIndex = Infinity;
					var divYears = calendar.getYears();

					if (divYears.length > 0) {
						//scan for where to insert the year
						divYears.each(function(index, divYear) {
							var insertYear = parseInt(year.label);
							var indexYear = parseInt($(divYear).html());
							if (insertYear < indexYear) {
								insertIndex = index;
								return false;
							}
						});
						if (insertIndex != Infinity) {
							// if not inserting at the end
							divYears.eq(insertIndex).before(year.element);
							// append the months
							for (i = 12; i >= 1; i--) {
								var sortItem = new SortItem(year.label, i, 0);
								sortItem.element.data("data", sortItem);
								sortListContent.find("#" + year.id).after(sortItem.element);
								sortItem.element.slideDown("slow");
							}
						} else {
							// append to the end
							sortListContent.append(year.element);
							// append the months
							for (i = 12; i >= 1; i--) {
								var sortItem = new SortItem(year.label, i, 0);
								sortItem.element.data("data", sortItem);
								sortListContent.find("#" + year.id).after(sortItem.element);
								sortItem.element.slideDown("slow");
							}
						}
					} else {
						// just add the year
						sortListContent.append(year.element);
						for (i = 1; i <= 12; i++) {
							var sortItem = new SortItem(year.label, i, 0);
							sortItem.element.data("data", sortItem);
							sortListContent.append(sortItem.element);
							sortItem.element.slideDown("slow");
						}
					}

				} else {
					//year exists

				}
			});
			calendar.years.sort(function(a, b) {
				if (a.label > b.label) return 1;
				if (a.label < b.label) return -1;
				if (a.label == b.label) return 0;
			});

			this.updateMonths();

		},
		updateMonths: function() {
			var sortListContent = this.sortListContent;
			var detailsContent = this.detailsContent;
			var calendar = this;
			var container = this.container;

			var visibleItems = calendar.detailsContent.find("div.item:visible");

			//reset the numbers
			calendar.getMonths().find("span").html("");

			calendar.getMonths().each(function() {
				var divMonth = $(this);
				var ID = divMonth.attr("id");
				var span = divMonth.find("span");
				var count = calendar.detailsContent.find(".item[rel='" + ID + "']:visible").length;
				if (count == 0) count = "";
				span.html(count);
			});


			calendar.getMonths().each(function(index, divMonth) {
				var number = $(divMonth).find("span").html();
				if (number == "" || number == "0") {
					$(divMonth).addClass("inactive");
				} else {
					$(divMonth).removeClass("inactive");
				}
			});

			this.updateDetailMonths()

		},
		updateDetailMonths: function() {
			var calendar = this;

			calendar.detailsContent.find(".group-by").hide();
			calendar.sortListContent.find(".item:not(.inactive)").each(function() {
				var id = $(this).attr("id");
				var detailGroupID = "#group" + id.replace("-", "");
				calendar.detailsContent.find(detailGroupID).show();
			});

		},
		setScrollable: function() {
			var sortScrollable = new Scrollable($(".scroll-calendar .sort-list"));
			var detailScrollable = new Scrollable($(".scroll-calendar .details"));
		},
		addDetailItem: function(detailItem) {

			// Only add items that don't exist
			if ($(this.detailItems.pluck("ID")).find(detailItem.ID).length == 0) {

				this.detailItems[this.detailItems.length] = detailItem;

				var detailMonth = detailItem.date.toString("M");
				var detailYear = detailItem.date.toString("yyyy");

				//Element to insert
				var detailElement = $(detailItem.element);
				detailElement.data("month", detailMonth);
				detailElement.data("year", detailYear);
				detailElement.data("sortID", detailYear + "-" + detailMonth);
				detailElement.data("date", detailItem.date);

				//Find the group to stick it under
				var detailGroups = this.detailsContent.find("#group" + detailYear + detailMonth + ".group-by");
				if (detailGroups.length > 0) {
					//Group exists
					var groupDate = Date.parse(detailYear + "-" + detailMonth + "-01");
					var detailGroup = new DetailGroup(detailItem.date.toString("MMMM"), groupDate);
					detailGroup.element.data("date", detailGroup.date);

					// INSERT Positioning algorithm here!! Otherwise list is UNSORTED
					//detailGroups.after(detailElement);

					var monthItem = detailGroups.next();
					var isLast = false;
					while (monthItem.data("date") < detailItem.date) {
						var nextItem = monthItem.next();
						if (nextItem.length == 0) {
							isLast = true;
							break;
						}
						monthItem = nextItem;

					}
					if (isLast) monthItem.after(detailElement);
					else monthItem.before(detailElement);

				}
				else {
					//Group DOESN'T exist
					//Determine where to insert group!

					var insertIndex = Infinity;
					this.detailsContent.find(".group-by").each(function(index, divGroup) {
						var group = $(this);
						var groupDate = group.data("date");
						var groupMonth = parseInt(groupDate.toString("M"));
						var groupYear = parseInt(groupDate.toString("yyyy"));

						if (detailItem.date < groupDate) {
							insertIndex = index;
							return false;
						}
					});

					//alert("inserting at " + insertIndex);

					var groupDate = Date.parse(detailYear + "-" + detailMonth + "-01");
					var detailGroup = new DetailGroup(detailItem.date.toString("MMMM"), groupDate);
					detailGroup.element.data("date", detailGroup.date);

					if (insertIndex != Infinity) {
						this.detailsContent.find(".group-by").eq(insertIndex).before(detailGroup.element);
						this.detailsContent.find(".group-by").eq(insertIndex + 1).before(detailElement);
					}
					else {
						this.detailsContent.append(detailGroup.element);
						this.detailsContent.append(detailElement);
					}
				}


				//this.detailsContent.append(detailElement);

				// Determine where to insert this detailItem.

				//this.loadMonths();

			}
		},
		sortDetailItems: function() {
			this.detailItems.sort(function(a, b) {
				return a.date.compareTo(b.date);
			});
			this.loadMonths();
			$("#cal_loading").hide();
		},
		scrollDetailTo: function() {
			var groupID = "#group" + this.currentYear + this.currentMonth;

			var detailGroup = this.details.find(groupID);
			if (detailGroup.length > 0) {
				var offsetTop = detailGroup[0].offsetTop;
				var scrollTop = detailGroup.scrollTop();
				var currentScrollTop = $(".details .scroll-content").scrollTop();

				//alert(groupID + " OffsetTop: " + offsetTop + " | ScrollTop: " + scrollTop + " | CurrentScrollTop: " + currentScrollTop);
				var scrollDiff = Math.abs(currentScrollTop - offsetTop);
				scrollDiff = (scrollDiff < 700) ? 700 : scrollDiff;
				$(".details .scroll-content").stop(true, false).animate({
					scrollTop: offsetTop
				}, scrollDiff, "swing");
			}

		},
		setEvents: function() {

			// Apply Sort Item Select event
			var outer = this; //do not jquery this object as it is a base2 object and will lost it's method references
			this.sortListContent.find(".item:not(.inactive)").live("click", function() {
				// Find the month 
				var divSortItem = $(this);
				calendar.sortListContent.find(".item.selected").removeClass("selected");
				divSortItem.addClass("selected");

				var sortItem = divSortItem.data("data");

				calendar.currentYear = sortItem.year;
				calendar.currentMonth = sortItem.month;

				calendar.scrollDetailTo();

			});

		},
		setCategory: function(category) {
			var calendar = this;

			calendar.filterCategory = category;
		},
		setLocation: function(location) {
			var calendar = this;

			calendar.filterLocation = location;
		},
		updateLocations: function() {

			var filterLocation = $(".filter.location");
			filterLocation.find('option').remove().end();

			filterLocation.append("<option value=''>- Location -</option>")
			$.get(calendarService, { a: "LOCATIONS", c: this.filterCategory }, function(data) {
				var locations = eval(data);

				for (var loc in locations) {
					if (locations[loc].venue_city)
						filterLocation.append("<option value='" + locations[loc].venue_city + "'>" + locations[loc].venue_city + "</option>")
				}

				// Set default value
				filterLocation.val(location);
			})
		},
		updatePerformances: function() {

			var calendar = this;

			//for (i = 0; i < calendar.detailItems.length; i++)
			//   calendar.detailItems.removeAt(i);

			calendar.detailItems = new base2.Array2();
			calendar.detailsContent.empty();

			// Get the results of the new filter
			$.get(calendarService, { a: 'PERFORMANCES', c: this.filterCategory, l: this.filterLocation }, function(data) {
				var performances = eval(data);
				var performance;

				//Pseudo-Multi Threading

				var processCounter = 0;
				var processLimit = performances.length;
				var processBusy = false;
				var processSpeed = 20;
				var processor = setInterval(function() {

					if (!processBusy) {
						processBusy = true;

						//process
						if (performances[processCounter] != undefined) {
							var id = performances[processCounter].performance_id;
							var performanceCheck = $("#perf_" + id);
							if (performanceCheck.length == 0) {
								performance = new DetailItem(performances[processCounter].performance_id, performances[processCounter].production_title, performances[processCounter].production_pagelink, performances[processCounter].venue_city, performances[processCounter].venue_title, performances[processCounter].performance_datetime, VirtualDirectory + performances[processCounter].image_1, performances[processCounter].performance_book_url, performances[processCounter].productioncategory_id, performances[processCounter].venue_city);
								calendar.addDetailItem(performance);
							}
						}


						// Final
						if (++processCounter == processLimit) {
							clearInterval(processor);

							calendar.sortDetailItems();
							calendar.updateFilter();
							calendar.updateMonths();
							calendar.scrollDetailTo();
						}
						//console.log(processCounter + ":" + processLimit);

						processBusy = false;
					}

				}, processSpeed);

				/*
				for (var p in performances) {
				if (performances[p].performance_id) {
				performance = new DetailItem(performances[p].performance_id, performances[p].production_title, performances[p].production_pagelink, performances[p].venue_city, performances[p].venue_title, performances[p].performance_datetime, VirtualDirectory + performances[p].image_1, performances[p].performance_book_url, performances[p].productioncategory_id, performances[p].venue_city);
				calendar.addDetailItem(performance);
				}
				}
				*/


			});


		},
		updateFilter: function() {
			var calendar = this;

			var filter = "";

			if (this.filterCategory != "") filter += ".cat-" + this.filterCategory;
			if (this.filterLocation != "") filter += "." + this.filterLocation.replace(" ", "");

			//alert("filtering: " + filter);
			if (filter != "") {
				calendar.detailsContent.find(".item:not(" + filter + ")").hide();
				calendar.detailsContent.find(filter).show();
			} else {
				calendar.detailsContent.find(".item").show();
			}

		},
		resetFilters: function() {
			var calendar = this;
			var container = this.container;

			container.find(".filter.category").val("").change();
			container.find(".filter.location").val("").change();
		}

	});


	/**
	 * Addes Scrollable events to a DOM structure
	 * @param {Object} container jQuery DOM container
	 */
	var Scrollable = base2.Base.extend({
		constructor: function(container) {
			
			this.container = $(container);
			this.scrollContent = this.container.find(".scroll-content");
			this.scrollUpElement = this.container.find(".scroll-up");
			this.scrollDownElement = this.container.find(".scroll-down");

			//this.container.css({ border: "4px solid #000"});

			this.bindEvents();
			
		},
		scrollDown: function() {
			var currentTop = this.scrollContent.scrollTop();
			var scrollTo = this.scrollContent.children(".scroll-wrapper").height() - this.scrollContent.height();
			
			var scrollSpeed = Math.abs(scrollTo - currentTop);
			this.scrollContent.animate({scrollTop: scrollTo}, scrollSpeed * 2);

		},
		scrollUp: function() {
			var currentTop = this.scrollContent.scrollTop();
			var scrollTo = 0;
			
			this.scrollContent.animate({scrollTop: scrollTo}, currentTop * 2);

		},
		scrollStop: function() {
			this.scrollContent.stop();

		},
		bindEvents: function() {
			var scrollable = this;
			
			this.scrollUpElement.live("mousedown", function() {
				scrollable.scrollUp();

			}).live("mouseup", function() {
				scrollable.scrollStop();

			}).mouseout(function() {
				scrollable.scrollStop();	
	
			});
			
			this.scrollDownElement.live("mousedown", function() {
				scrollable.scrollDown();
				
			}).live("mouseup", function() {
				scrollable.scrollStop();
				
			}).mouseout(function() {
				scrollable.scrollStop();
				
			});
		}
	});
	
	
	/**
	 * An individual item in the sort list
	 */
	var SortItem = base2.Base.extend({
		constructor: function(year, month, number) {
			this.id = year + "-" + month;
			this.year = year;
			this.month = month;
			this.number = number;
			this.monthName = Date.CultureInfo.monthNames[month-1];
			
			this.applySkin(SortItemSkin);
		},
		applySkin: function(skin) {
			skin = skin.replace("@ID", this.id);
			skin = skin.replace("@Label", this.monthName);
			skin = skin.replace("@Number", (this.number == 0)? "" : this.number);
			this.element = $(skin);
			return this.element;
		},
		toString: function() {
			return this.id;
		},
		refreshNumber: function() {

		},
		incrementNumber: function() {
			this.number ++;
			return this.number;
		},
		decrementNumber: function() {
			this.number --;
			return this.number;
		}
	});
	
	/**
	 * A Sort Group Item
	 */
	var SortGroup = base2.Base.extend({
		constructor: function(label, enabled) {
			this.id = label;
			this.label = label;
			this.enabled = enabled;
			this.applySkin(SortGroupSkin);

		}, 
		applySkin: function(skin) {
			skin = skin.replace("@ID", this.id);
			skin = skin.replace("@Label", this.label);
			
			this.element = $(skin);
			return this.element;
		},
		toString: function() {
			return this.id;
		}
	});
	
	/**
	 * An individual event item in the details list
	 */
	var DetailItem = base2.Base.extend({
	    constructor: function(id, title, productionUrl, city, venue, date, thumbnail, bookUrl, category, location) {
	        this.ID = "perf_" + id;
	        this.date = date;
	        this.thumbnail = thumbnail;
	        this.title = title;
	        this.city = city;
	        this.venue = venue;
	        this.productionUrl = productionUrl;
	        this.bookUrl = bookUrl;
	        this.category = (category == null) ? "" : category;
	        this.location = location;
	        if (this.date) this.rel = this.date.toString("yyyy") + "-" + this.date.toString("M");

	        this.applySkin(DetailItemSkin);
	    },
	    applySkin: function(skin) {

	        if (this.productionUrl == null) this.productionUrl = '';

	        this.productionUrl = VirtualDirectory + this.productionUrl;
	        
	        skin = skin.replace("@ID", this.ID);
	        skin = skin.replace("@Date", this.date.toString("ddd d"));
	        skin = skin.replace("@Time", this.date.toString("h.mmtt"));
	        skin = skin.replace("@Title", this.title);
	        skin = skin.replace("@ProductionUrl", this.productionUrl);
	        skin = skin.replace("@BookUrl", this.productionUrl);
	        skin = skin.replace("@City", this.city);
	        skin = skin.replace("@Venue", this.venue);
	        skin = skin.replace("@Image", this.thumbnail);
	        skin = skin.replace("@Rel", this.rel);
	        skin = skin.replace("@Category", "cat-" + this.category);
	        skin = skin.replace("@Location", this.location.replace(" ", ""));

	        this.element = $(skin);


	        return this.element;
	    }
	});
	
	/**
	 * An group element in the details list.
	 * @param {Object} label
	 * @param {Object} date
	 */
	var DetailGroup = base2.Base.extend({
		constructor: function(label, date) {
			this.ID = "group" + date.toString("yyyy") + date.toString("M");
			this.label = label;
			this.date = date;
			
			this.applySkin(DetailGroupSkin);
		},
		applySkin: function(skin) {
			skin = skin.replace("@ID", this.ID);
			skin = skin.replace("@Label", this.label);
			
			this.element = $(skin);
			return this.element;
		}
	});
	
	
	var CategoryFilter = base2.Base.extend({
		constructor: function() {
			
		},
		reset: function() {
			
		}		
	});
	
	
	/** 
	 * Skin for the detail item
	 */
	var DetailItemSkin = "<div id=\"@ID\" class=\"item @Category @Location\" rel=\"@Rel\"><div class=\"cell col1\">@Date<br>@Time</div><div class=\"cell col2\"><a href=\"@BookUrl\"><img src=\"@Image\" class=\"thumb\" border=\"0\" alt=\"\" /></a></div><div class=\"cell col3\"><a href=\"@ProductionUrl\">@Title</a></div><div class=\"cell col4\">@City<br />@Venue</div></div>";
	
	var DetailGroupSkin = "<div id=\"@ID\" class=\"group-by\">@Label</div>";
	
	/** 
	 * Skin for the sort item
	 */
	var SortItemSkin = "<div id=\"@ID\" class=\"item\"><span>@Number</span>@Label</div>";
	
	var SortGroupSkin = "<div id=\"@ID\" class=\"group-by\">@Label</div>";
	

	var ajaxDates = {
		"year": "2009", "month": "January", "total": "7"
	};
	
	var ajaxPerformance = {
		"date": "2009-03-11 19:30",
		"thumbnail": "images/performance/cal/sample1.jpg",
		"title": "Gidon KREMER & Kremerata Baltica",
		"city": "Melbourne",
		"venue": "Melbourne Arts Theatre"
	};
