if( ! window['syncopate'] ) {
	window['syncopate'] = {};
	var syncopate = window['syncopate'];
}


(function($){

	$.browser.mobile = (navigator.userAgent.toLowerCase().indexOf('mobile') != -1 || navigator.userAgent.toLowerCase().indexOf('android') != -1 || navigator.userAgent.toLowerCase().indexOf('palm') != -1);

	$(document).ready(function() {
		syncopate.debug = ( window.location.hostname == '127.0.0.1' );
		syncopate.relativeDates();
		syncopate.forms();
		syncopate.feedback();
		syncopate.widgets();
		syncopate.fixHeight();
		syncopate.spotlight();
		syncopate.lightbox();
		syncopate.dashboard();
		syncopate.messages();
		$.datepicker.setDefaults( { 'dateFormat': 'yy-mm-dd' } );
		$('form .date input').datepicker();
		syncopate.timepicker();
		try {
			$('textarea[rel=wysiwyg]').wysiwyg({'css':$('link[rel=stylesheet][href$=syncopate.css]').attr('href').replace('syncopate.css','wysiwyg-overrides.css')});
		} catch(e) { /* do nothing */ }
		syncopate.typeaheadForms();
		syncopate.S3_STORAGE_URL = $('script[rel]').attr('rel');
		syncopate.ROOTURL = window.location.protocol + '//' + window.location.host;
		syncopate.audioPlayers();
		syncopate.maps();
		syncopate.like();
		syncopate.addToPlaylist();
		$('a[target=_parent]').click(function() {
			if( self.opener ) {
				self.opener.location = $(this).attr('href');
				self.opener.focus();
				return false;
			} else {
				$(this).attr({'target': '_blank'});
				return true;
			}
		});
		syncopate.playerWindow = self.opener;
		syncopate.player();
		syncopate.geolocate();
	});
	
	$(window).load(function() {
		syncopate.fixHeight();
	});
	
	$(window).resize(function() {
		syncopate.fixHeight();
	});
	
	function log( item ) {
		if( syncopate.debug && typeof window['console'] != 'undefined' ) {
			console.log( item );
		}
	}
	
	function apnumber( number ) {
		number = parseInt( number, 10 );
		switch(number) {
			case 0:
				number = 'zero';
				break;
			case 1:
				number = 'one';
				break;
			case 2:
				number = 'two';
				break;
			case 3:
				number = 'three';
				break;
			case 4:
				number = 'four';
				break;
			case 5:
				number = 'five';
				break;
			case 6:
				number = 'six';
				break;
			case 7:
				number = 'seven';
				break;
			case 8:
				number = 'eight';
				break;
			case 9:
				number = 'nine';
				break;
			default:
				break;
		}
		return number;
	}

	function apnumber_reverse( number ) {
		number = $.trim(number);
		switch(number) {
			case 'zero':
				number = 0;
				break;
			case 'one':
				number = 1;
				break;
			case 'two':
				number = 2;
				break;
			case 'three':
				number = 3;
				break;
			case 'four':
				number = 4;
				break;
			case 'five':
				number = 5;
				break;
			case 'six':
				number = 6;
				break;
			case 'seven':
				number = 7;
				break;
			case 'eight':
				number = 8;
				break;
			case 'nine':
				number = 9;
				break;
			default:
				break;
		}
		number = parseInt( number, 10 );
		return number;
	}
	
	function intcomma( number ) {
		origNumber = number;
		number = parseInt( number, 10 );
		if( isNaN(number) ) {
			return origNumber;
		}
		numString = String( number );
		number = "";
		var loopCount = 0;
		for (var i = numString.length - 1; i >= 0; i--){
			number = ( loopCount % 3 === 2 && i > 0 ? ',' : '' ) + numString[i] + number;
			loopCount++;
		};
		return number;
	}
	
	var protos = {
		'sidebar': $('<div class="sidebar" />'),
		'prev': $('<a href="#previous" title="Previous" class="prev">&laquo; Previous</a>'),
		'next': $('<a href="#previous" title="Previous" class="next">Next &raquo;</a>'),
		'ul': $('<ul />'),
		'li': $('<li />'),
		'a': $('<a />'),
		'mapHolder': $('<div class="map-holder" />'),
		'typeahead': {
			'input': $('<input type="text" class="typeahead-input" autocomplete="off" />'),
			'fauxInput': $('<div class="typeahead-fauxinput" />'),
			'span': $('<span class="typeahead-result" />'),
			'remove': $('<a href="#remove" class="remove">&times;</a>'),
			'resultsUL': $('<ul class="typeahead-results" />'),
			'resultsLI': $('<li />')
		},
		'select': $('<select />'),
		'option': $('<option />'),
		'clear': $('<br class="clear" />'),
		'audio': $('<audio autoplay controls />'),
		'embed': $('<embed />'),
		'div': $('<div />'),
		'span': $('<span />'),
		'label': $('<label />'),
		'p': $('<p />'),
		'img': $('<img  />'),
		'tfoot': $('<tfoot />'),
		'tr': $('<tr />'),
		'td': $('<td />'),
		'table': $('<table />'),
		'button': $('<button />')
	}
	
	syncopate.forms = function() {
		var errorMessage = $('<span class="error-message" />');
		var checkmark = $('<span class="ok">&#x2713;</span>');

		var signup = function() {
			if( ! $('body').is('#signup') ) { return; }
			var form = $('#main form');
			var inputs = form.find('input');

			var first_name = form.find('input#id_first_name');
			first_name.blur(function() {
				if( ! first_name.val() ) {
					handleError( first_name, 'You must enter your first name' );
				} else {
					clearError( first_name );
				}
			});

			var last_name = form.find('input#id_last_name');
			last_name.blur(function() {
				if( ! last_name.val() ) {
					handleError( last_name, 'You must enter your last name' );
				} else {
					clearError( last_name );
				}
			});

			var username = form.find('input#id_username');
			username.blur(function() {
				if( ! username.val() ) {
					handleError( username, 'You must enter a username' );
				} else if( username.val().length > 30 ) {
					handleError( username, 'Usernames must be 30 characters or less' );
				} else if( username.val().match(/[^A-Za-z0-9_]/g) ) {
					handleError( username, 'Usernames must be letters, numbers or underscores (_) only' );
				} else {
					$.ajax({
						'url': '/user/' + username.val(),
						'dataType': 'html',
						'complete': function(request, status) {
							if( status == 'success' ) {
								handleError( username, 'Username is not available' );
							} else if( status == 'error') {
								clearError( username );
							}
						}
					})
				}
			});

			var email = form.find('input#id_email');
			email.blur(function() {
				if( ! email.val() ) {
					handleError( email, 'You must enter an email address' );
				} else if( ! email.val().match(/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i) ) {
					handleError( email, 'This is not a valid email address' );
				} else {
					clearError( email );
				}
			});

			var password = form.find('input#id_password1');
			password.blur(function() {
				if( ! password.val() ) {
					handleError( password, 'You must enter a password' );
				} else {
					clearError( password );
				}
			});

			var passwordConfirm = form.find('input#id_password2');
			passwordConfirm.blur(function() {
				if( ! passwordConfirm.val() ) {
					handleError( passwordConfirm, 'You must confirm your password' );
				} else if( password.val() != passwordConfirm.val() ) {
					handleError( passwordConfirm, 'Your passwords do not match' );
				} else {
					clearError( passwordConfirm );
				}
			});
			
			inputs.focus(function() {
				$(this).parent('li').find('.ok,.error-message').remove();
			});

			form.submit(function(s) {
				var validates = true;
				
				inputs.blur();
				
				if( form.find('.error-message').size() ) {
					validates = false;
				}
				
				return validates;
			});
		}
		
		var handleError = function( item, message ) {
			try {
				var parent = item.parent('li');
				var container = errorMessage.clone();
				container.text( message );
				parent.find('.ok,.error-message').remove();
				parent.append( container );
			} catch(e) {
				// do nothing
			}
		}
		
		var clearError = function( item ) {
			try {
				item.parent('li').append( checkmark.clone() ).find('.error-message').remove();
			} catch(e) {
				// do nothing
			}
		}
		
		signup();
		
		$('li.filters select, #sb .filters select').each(function() {
			var select = $(this);
			var button = $(this).siblings('button');
			button.hide();
			select.change(function() {
				window.location = select.val();
			});
		});
		$('#main table thead th').click(function() {
			var header = $(this);
			url = $('.filters select option').filter(function() { return $.trim($(this).text()) == $.trim(header.text()) }).val();
			if( url ) {
				window.location = url;
			}
		});
	}
	
	syncopate.feedback = function() {
		var messageHolders = $('#bd > ul.errors, #bd > ul.messages');
		var close = $('<li class="close"><a href="#close">&times;</a></li>');
		messageHolders.each(function() {
			var holder = $(this);
			var closer = close.clone();
			closer.find('a').click(function(c) {
				c.preventDefault();
				holder.slideUp(1000);
			});
			closer.appendTo(holder);
		});
	}
	
	syncopate.widgets = function() {
	}
	
	syncopate.fixHeight = function() {
		var bdHeight = $('#bd').height();
		var diff = $('html').height() - ( $('header').outerHeight(true) + $('footer').outerHeight(true) + bdHeight );
		if( diff > 0 ) {
			$('#bd').height( bdHeight + diff );
		}

		var thumbs = $('.thumb:nth-child(4n+1)');
		thumbs = thumbs.add($('.thumb').eq(0));
		thumbs.each(function() {
			var siblings = $(this);
			siblings = siblings.add($(this).next('.thumb')).add($(this).next('.thumb').next('.thumb'));
			var heighest = 0;
			siblings.each(function() {
				heighest = $(this).height() > heighest ? $(this).height() : heighest;
			});
			siblings.height(heighest);
		});

		var holders = $('.widgets');
		holders.each(function() {
			var widgets = $(this).find('.widget:first-child, .widget:nth-child(3n+1)');
			widgets.each(function() {
				var siblings = $(this);
				siblings = siblings.add($(this).next('.widget')).add($(this).next('.widget').next('.widget'));
				var heighest = 0;
				siblings.each(function() {
					heighest = $(this).height() > heighest ? $(this).height() : heighest;
				});
				siblings.height(heighest);
			});
		});
		
		var twoCols = $('.widget.album:nth-child(odd)');
		twoCols.each(function() {
			var odd = $(this);
			var even = $(this).next('.widget.album');
			if ( ! even.size() ) { return; }
			if( odd.height() < even.height() ) {
				odd.height(even.height());
			} else {
				even.height(odd.height());
			}
		});
		
		var formLIs = $('form > ol > li');
		formLIs.each(function() {
			var li = $(this);
			var form = li.parents('form');
			if( li.outerWidth() > ( form.width() / 2 ) || li.is('.hidden') || li.is('.wysiwyg') ) { return; }
			var next = li.next('li');
			if( li.css('float') == 'left' && next.width() == li.width() && ! next.is('.hidden') && ! next.is('.wysiwyg') ) {
				next.css({'float': 'right'})
				if( next.height() > li.height() ) {
					li.height(next.height());
				} else {
					next.height(li.height());
				}
			}
		});
	}
	
	syncopate.spotlight = function() {
		var searchLi = $('header nav li.search');
		var searchButton = searchLi.find('a');
		var searchUrl = searchButton.attr('href');
		var sheet = $('<div class="search-sheet"></div>')
		var input = $('<input type="text" name="q" autocomplete="off" />');
		var loader = false;
		
		sheet.hide().appendTo( searchLi ).append( input );;
		input.wrap( '<div class="input-wrapper" />' );
		
		$(window).keypress(function(e) {
			if(e.ctrlKey && ( e.which == 115 || e.which == 83 ) ) {
				e.stopPropagation();
				searchButton.click();
			}
		})
		
		var getCurrentItem = function() {
			return sheet.find('.search-results li.selected');
		}
		
		var scrollToCurrent = function( currentItem ) {
			var newCurrent = getCurrentItem();
			var diff = (newCurrent.position().top) - ( currentItem.size() ? currentItem.position().top : 0 );
			var results = sheet.find('.search-results');
			results.scrollTop(results[0].scrollTop + diff);
		}
		
		input.keyup(function(e) {
			e.stopPropagation();
			var pressed = e.which;
			var currentItem = getCurrentItem();
			var currentHref = currentItem.find('a').attr('href');
			switch( pressed ) {
				case 38: // Up arrow
					if( currentItem.size() && currentItem.prev('li').size() ) {
						currentItem.removeClass('selected').prev('li').addClass('selected');
					} else if( currentItem.size() && currentItem.parents('dd').prev('dt').prev('dd').size() ) {
						currentItem.removeClass('selected').parents('dd').prev('dt').prev('dd').find('li:last-child').addClass('selected');
					} else {
						currentItem.removeClass('selected');
						sheet.find('dl dd:last-child li:last-child').addClass('selected');
					}
					scrollToCurrent(currentItem);
					break;
				case 40: // Down arrow
					if( currentItem.size() && currentItem.next('li').size() ) {
						currentItem.removeClass('selected').next('li').addClass('selected');
					} else if( currentItem.size() && currentItem.parents('dd').next('dt').next('dd').size() ) {
						currentItem.removeClass('selected').parents('dd').next('dt').next('dd').find('li:first-child').addClass('selected');
					} else {
						currentItem.removeClass('selected');
						sheet.find('dl dt:first-child + dd li:first-child').addClass('selected');
					}
					scrollToCurrent(currentItem);
					break;
				case 13: // Return
					if ( currentItem.size() ) {
						window.location = currentItem.find('a').attr('href');
					}
					break;
				case 27: // Escape
					if ( input.val() ) { // clear the data
						currentItem.removeClass('selected');
						input.val('');
						sheet.find('.search-results').remove();
					} else {
						searchButton.click(); // close the search sheet
					}
					break;
				default: // string handling
				if( input.val().length >= 3 ) { // ajax lookup
					if( typeof loader != 'undefined' && loader ) {
						var prevLoader = loader;
						try {
							prevLoader.abort(); // If we have already started a request, kill it to reduce server load
						} catch(e) {
							// do nothing
						}
					}
					loader = $.ajax({
						'cache': false,
						'url': searchUrl,
						'type': 'POST',
						'data': {
					 		'q': input.val()
						},
						'success': function(data){
							sheet.find('.search-results').remove();
							$(data).find('.search-results').appendTo(sheet);
						},
						'error': function() {
							// do nothing
						}
					});
				} else {
					sheet.find('.search-results').remove();
				}
			}
		})

		searchButton.click(function(c) {
			c.preventDefault()
			searchLi.toggleClass('on');
			if( searchLi.is('.on') ) {
				sheet.fadeIn(500);
				input.focus();
			} else {
				sheet.fadeOut(500, function() {
					sheet.find('.search-results').remove();
					input.val('');
				});
			}
		});
	}
	
	syncopate.lightbox = function() {
		var links = $('a[rel=lightbox]');
		var overlay = $('#overlay').size() ? $('#overlay') : protos.div.clone().attr({'id': 'overlay'}).css({'display': 'none'});
		var container = protos.div.clone().attr({'id': 'lightbox'}).css({'display': 'none'});
		var close = protos.a.clone().attr({'href': '#close'}).addClass('close').html('&times; Close');
		var target = protos.div.clone().addClass('target');
		var prev = protos.a.clone().attr({'href': '#previous'}).addClass('prev').html('&laquo; Previous');
		var next = protos.a.clone().attr({'href': '#next'}).addClass('next').html('Next &raquo;');
		var title = protos.label.clone();
		var slideshow = null;
		var slideshowButton = protos.a.clone().attr({'href': '#play', 'title': 'Play Slideshow'}).addClass('slideshow').html('Play Slideshow');
		
		overlay.click(function() {
			close.click();
		});
		
		container.click(function(e) {
			e.stopPropagation();
		});

		$('body').append(overlay).append(container);
		container.append(close).append(target).append(prev).append(next).append(title).append(slideshowButton);
		container.show().css({'top': Math.round((($(window).height() > window.innerHeight ? window.innerHeight : $(window).height()) - container.outerHeight()) / 2) + 'px', 'left': Math.round(($(window).width() - container.outerWidth()) / 2) + 'px', 'margin-top': 0, 'margin-left': 0}).hide();
		close.click(function(c) {
			c.preventDefault();
			overlay.add(container).fadeOut('normal');
			stopSlideshow();
		});
		
		var changePhoto = function(elem) {
			var current = parseInt(links.filter('.selected').attr('lb-position'),10);
			var to = elem.is('.prev') ? links.eq(current - 1) : links.eq(current + 1);
			if(!to.size()) {
				to = elem.is('.prev') ? links.eq(links.size() - 1) : links.eq(0);
			}
			if(to.size()) {
				to.click();
			}
		}
		
		prev.add(next).click(function(c) {
			c.preventDefault();
			changePhoto($(this));
			stopSlideshow();
		});
		
		var stopSlideshow = function() {
			clearInterval( slideshow );
			slideshowButton.removeClass('playing').text('Play Slideshow');
		}
		
		var startSlideshow = function() {
			slideshow = setInterval(function() {
				changePhoto(next);
			}, 5000);
			slideshowButton.addClass('playing').text('Stop Slideshow');
		}
		
		slideshowButton.click(function(c) {
			c.preventDefault();
			if( slideshowButton.is('.playing') ) {
				stopSlideshow();
			} else {
				startSlideshow();
			}
		});

		links.each(function(index) {
			var link = $(this);
			link.click(function(c) {
				c.preventDefault();
				open(link.attr('href'),link.attr('title'));
				links.filter('.selected').removeClass('selected');
				link.addClass('selected');
			});
			link.attr({'lb-position': index});
		});

		var open = function(url, titleText) {
			if(container.is(':visible')) {
				target.children().add(title).fadeOut('normal', function() {
					target.children().remove();
					loadImage(url, titleText);
				});
			} else {
				target.children().remove();
				title.hide();
				overlay.add(container).fadeIn('normal',function(){
					loadImage(url, titleText);
				});
			}
		}

		var loadImage = function(url, titleText) {
			if(container.is('.loading')) { return; }
			container.addClass('loading');

			var img = new Image();
			img.onload = function() {
				img.style.display = 'none';

				var maxWidth = ($(window).width() - parseInt(container.css('padding-left'),10) - parseInt(container.css('padding-right'), 10)) - 100;
				var maxHeight = (($(window).height() > window.innerHeight ? window.innerHeight : $(window).height()) - parseInt(container.css('padding-top'),10) - parseInt(container.css('padding-bottom'), 10)) - 100;

				if(img.width > maxWidth || img.height > maxHeight) { // One of these is larger than the window
					var ratio = img.width / img.height;
					if(img.height >= maxHeight) {
						img.height = maxHeight;
						img.width = maxHeight * ratio;
					} else {
						img.width = maxWidth;
						img.height = maxWidth * ratio;
					}
				}
				
				title.text( titleText );

				container.animate({'width': img.width + 2,'height': img.height + 2, 'top': Math.round((($(window).height() > window.innerHeight ? window.innerHeight : $(window).height()) - img.height - parseInt(container.css('padding-top'),10) - parseInt(container.css('padding-bottom'),10) + 4) / 2) + 'px', 'left': Math.round(($(window).width() - img.width - parseInt(container.css('padding-left'),10) - parseInt(container.css('padding-right'),10) + 4 ) / 2) + 'px'},'normal', function(){
					target.append(img);
					$(img).add(title).fadeIn('normal', function() {
						container.removeClass('loading');
					}).click(function(){
						stopSlideshow();
						next.click();
					});
				})
			}
			img.src = url;
		}
	}
	
	syncopate.dashboard = function() {
		if( ! $('.dashboard').size() ) { return; }
		
		var widgets = $('.dashboard > .widget');
		widgets.addClass('closed').find('h2 a').click(function(c) {
			c.stopPropagation();
		});
		var oldHash = false;
		var handleHash = function() {
			hash = window.location.hash.replace('#','');
			if ( oldHash == hash ) { oldHash = hash; return; }
			if( oldHash && ! hash ) {
				widgets.eq(0).find('.sidebar h3:first-child').click();
				return;
			}
			try {
				var header = widgets.find('.sidebar h3[rel=' + hash + ']');
				header.click();
				if( header.parents('.widget').is('.closed') ) {
					widgets.addClass('closed');
					window.scrollTo(0, header.parents('.widget').removeClass('closed').offset().top);
				}
			} catch(e) {}
			oldHash = hash;
		}
		widgets.each(function() {
			var widget = $(this);
			var sections = widget.find('.section');
			var sidebar = protos.sidebar.clone();
			var widgetHeader = widget.find('h2');
			widgetHeader.after(sidebar);
			var id = widgetHeader.parents('.widget').attr('id');
			widgetHeader.click(function() {
				widgets.filter('.widget:not(.closed)').addClass('closed');
				widget.removeClass('closed');
				window.scrollTo(0,widget.offset().top);
			}).css({
				'cursor': 'pointer'
			});
			sections.each(function() {
				var section = $(this);
				var header = section.find('h3');
				header.appendTo(sidebar);
				header.attr({'rel': id + '-' + section.attr('rel')});
				header.click(function() {
					sections.hide();
					section.show();
					sidebar.find('h3.selected').removeClass('selected');
					header.addClass('selected');
					window.location.hash = header.attr('rel');
				});
			});
			widget.find('.manage-links').appendTo(sidebar);
			sections.hide().eq(0).show();
			sidebar.find('h3:first-child').addClass('selected');
		});
		handleHash();
		widgets.addClass('scripted');
		if( ! oldHash ) {
			widgets.eq(0).removeClass('closed').find('.sidebar h3:first-child').click();
		}
		
		setInterval(function(){
			handleHash();
		},250);
		
		var changeTablePage = function(groups, dir, table) {
			var currentGroup = parseInt( table.attr('data-current-group'), 10 );
			var nextGroup = dir === 'prev' ? currentGroup - 1 : currentGroup + 1;

			if( typeof groups[nextGroup] != 'undefined' ) {
				groups[currentGroup].fadeOut(500, function() {
					groups[nextGroup].fadeIn(500);
					table.attr({'data-current-group': nextGroup});
				});
			}
		};
		
		var paginateTables = function() {
			var tables = widgets.find('table').filter(':not(.no-pagination)');
			tables.each(function() {
				var table = $(this);
				var tbody = table.find('tbody')
				var rows = tbody.find('tr');
				if( rows.size() < 11 ) { return; }
				var groups = [];
				for (var i=0; i < Math.ceil(rows.size() / 10); i++) {
					var start = i*10;
					var end = start+10;
					groups.push( rows.slice(start, end) );
				};
				rows.hide();
				groups[0].show();
				table.attr({'data-current-group': '0'});
				var prev = protos.prev.clone();
				var next = protos.next.clone();
				prev.add(next).appendTo(table.find('tfoot tr td.spacer').text('')).click(function(c) {
					c.preventDefault();
					var dir = $(this).is('.prev') ? 'prev' : 'next';
					changeTablePage(groups, dir, table);
				});
			});
		}
		
		var handleActions = function() {
			var overlay = $('#overlay').size() ? $('#overlay') : protos.div.clone().attr({'id': 'overlay'}).css({'display': 'none'});
			var formHolderWrapper = protos.div.clone().attr({'id': 'form-holder'}).css({'display': 'none'});
			var formHolder = protos.div.clone().addClass('target');
			overlay.click(function() {
				formHolderWrapper.hide();
				formHolder.empty();
			});
			formHolder.click(function(c) {
				c.stopPropagation();
			});
			var ajaxTemp = protos.div.clone();
			formHolder.appendTo(formHolderWrapper.appendTo($('body')));
			var close = protos.a.clone().attr({'href': '#close'}).addClass('close').html('&times; Close');
			close.appendTo(formHolderWrapper).click(function(c) {
				c.preventDefault();
				formHolderWrapper.add(overlay).hide();
			});
			var deletes = $('.dashboard a.delete');
			deletes.live('click', function(c) {
				if( c.button == 2 ) { return true; }
				c.preventDefault();
				var del = $(this);
				var row = del.parents('tr');
				var type = row.attr('type') ? "the " + row.attr('type') + " " : "";
				var name = row.find('.name span').size() ? "“" + $.trim(row.find('.name span').text()) + "”" : "";
				syncopate.confirm("Are you sure you want to delete " + type +  name + "?", function() {
					del.parent('td').addClass('loading').children().hide();
					$.ajax({
						'url': del.attr('href'),
						'type': 'POST',
						'data': {
							'confirm': true,
						},
						'dataType': 'html',
						'complete': function() {
							del.parent('td').removeClass('loading').children().show();
						},
						'success': function() {
							row.remove();
							paginateTables();
						},
						'error': function() {
							syncopate.alert(name + " could not be deleted.");
						}
					});
				});
			});
			var add_edits = $('.dashboard a.add, .dashboard a.edit');
			add_edits.live('click', function(c) {
				if( c.button == 2 ) { return true; }
				c.preventDefault();
				var link = $(this);
				overlay.show();
				formHolder.empty();
				formHolderWrapper.show().addClass('loading');
				ajaxTemp.load(link.attr('href'),
					function(){
						formHolderWrapper.removeClass('loading');
						formHolder.append(ajaxTemp.find('#main h1'));
						var form = ajaxTemp.find('#main form');
						form.find('button[value=add],button[value=continue]').remove();
						setTimeout(function(){
							$('form .date input').datepicker();
							syncopate.feedback();
							syncopate.timepicker();
							syncopate.typeaheadForms();
							try {
								$('textarea[rel=wysiwyg]').wysiwyg({'css':$('link[rel=stylesheet][href$=syncopate.css]').attr('href').replace('syncopate.css','wysiwyg-overrides.css')});
							} catch(e) { /* do nothing */ }
						},10);
						form.prepend(ajaxTemp.find('.widget.photo-preview img'));
						ajaxTemp.empty();
						form.ajaxForm({
							'beforeSubmit': function() {
								if( syncopate.isTypeaheadEvent ) {
									return false;
								}
								form.hide();
								formHolderWrapper.addClass('loading');
								formHolder.find('ul.messages,ul.errors').remove();
							},
							'success': function(responseText) {
								var response = $(responseText);
								formHolderWrapper.removeClass('loading');
								if( response.find('.dashboard').size() ) {
									syncopate.notifiers(response.find('ul.messages,ul.errors'));
									var section = link.parents('.section');
									var updatedSection = response.find('#' + section.parents('.widget').attr('id') + ' .section[rel=' + section.attr('rel') + ']');
									if( updatedSection.size() ) {
										section.replaceWith(updatedSection.show());
										paginateTables();
									}
									overlay.add(formHolderWrapper).hide();
									formHolder.empty();
								} else {
									form.show();
									formHolder.prepend(response.find('ul.messages,ul.errors'));
								}
							},
							'url': link.attr('href')
						});
						formHolder.append(form);
					}
				);
			});
		}
		handleActions();
		
		var songs = $('table.songs tbody tr');
		var albums = $('table.albums tbody tr');
		
		syncopate.dragAndDrop( songs, albums );

		var photos = $('table.photos tbody tr');
		var folders = $('table.folders tbody tr');
		
		syncopate.dragAndDrop( photos, folders );
	}
	
	syncopate.timepicker = function() {
		var inputs = $('form .time input');
		var option = $('<option />')
		var hour = $('<select class="hour"></select>');
		var minutes = $('<select class="min"></select>');
		var meridian = $('<select class="meridian"><option value="0">a.m.</option><option value="12">p.m.</option></select>');
		var nullOption = $('<option value="--" selected="selected">--</option>');

		for (var i = 13 - 1; i >= 1; i--){
			hour.prepend(option.clone().attr({'value': i}).text(i));
		};
		
		for (var i = 55; i >= 0; i = i - 5) {
			var val = i < 10 ? '0' + i : i;
			minutes.prepend(option.clone().attr({'value': val }).text(val));
		};

		var hourTo24 = function( hour, meridian ) {
			var val = parseInt( hour.val(), 10 ) + parseInt( meridian.val(), 10 );
			if ( val == 24 ) {
				val = '00';
			} else if ( val < 10 ) {
				val = '0' + val; 
			}
			return val;
		}
		
		var handleTimeChange = function( input, hour, minutes, meridian ) {
			if( hour.val() == '--' || minutes.val() == '--' || meridian.val() == '--' ) {
				input.val('');
			}
			input.val( hourTo24( hour, meridian ) + ':' + minutes.val() + ':00' );
		}
		
		var handleDefaults = function( input, hour, minutes, meridian ) {
			hour.add(minutes).add(meridian).find('[selected]').removeAttr('selected');
			var time = input.val().split(':');
			if ( ! time || time[0] == "" ) { return; }
			minutes.find('option[value=' + time[1] + ']').attr({'selected':'selected'});
			if ( time[0] == '00' ) {
				hour.find('option[value=12]').click();
				meridian.find('option[value=12]').attr({'selected':'selected'});
			} else if ( parseInt(time[0],10) > 12 ) {
				hour.find('option[value=' + ( parseInt(time[0],10) - 12 ) + ']').attr({'selected':'selected'});
				meridian.find('option[value=12]').attr({'selected':'selected'});
			} else {
				hour.find('option[value=' + time[0] + ']').attr({'selected':'selected'});
				meridian.find('option[value=0]').attr({'selected':'selected'});
			}
		}
		
		inputs.each(function() {
			var input = $(this);
			if( input.siblings('select').size() ) { return; }
			input.hide();
			var thisHour = hour.clone();
			var thisMinutes = minutes.clone();
			var thisMeridian = meridian.clone();
			if( ! input.parent().is('.required') ) {
				thisHour.prepend(nullOption.clone());
				thisMinutes.prepend(nullOption.clone());
				thisMeridian.prepend(nullOption.clone());
			} else {
				thisHour.prepend(nullOption.clone().attr({'disabled':'disabled'}));
				thisMinutes.prepend(nullOption.clone().attr({'disabled':'disabled'}));
				thisMeridian.prepend(nullOption.clone().attr({'disabled':'disabled'}));
			}
			
			handleDefaults( input, thisHour, thisMinutes, thisMeridian );
			
			thisHour.add(thisMinutes).add(thisMeridian).appendTo(input.parent()).change(function() {
				handleTimeChange(input, thisHour,thisMinutes,thisMeridian);
			});;
		});
	}
	
	syncopate.dragAndDrop = function( draggables, droppables ) {
		var main = $('#main');
		
		if ( ! draggables.size() || ! droppables.size() ) { return; }

		draggables.draggable({
			'appendTo': main,
			'containment': main,
			'cursor': 'move',
			'helper': 'clone',
			'opacity': 0.7,
			'revert': true,
			'scope': draggables.parents('table').attr('scope')
		});
		
		droppables.droppable({
			'activeClass': 'highlight',
			'hoverClass': 'over',
			'scope': draggables.parents('table').attr('scope'),
			'drop': function(event, ui) {
				var target = $(this);
				var missile = ui.draggable;
				var data = {};
				$.each(target[0].attributes, function() {
					if( this.name.indexOf('data-') > -1 ) {
						data[this.name.replace('data-','')] = this.nodeValue;
					}
				});
				$.ajax({
					'url': missile.find('a.edit').attr('href'),
					'data': data,
					'error': function(request, textStatus, error) {
						syncopate.alert('Sorry, but we couldn\'t make the change');
					},
					'success': function(data, textStatus) {
						missile.find('.' + target.attr('type')).text(target.find('.name').text())
						missile.addClass('over');
						setTimeout(function() {
							missile.removeClass('over');
						},2000);
					},
					'type': 'POST',
					'cache': false
				})
			}
		});
		
	}
	
	syncopate.messages = function() {
		var table = $('table.messages');
		var form = table.parents('form');
		if( ! table.size() || ! form.size() ) { return; }
		
		var checkboxes = form.find('input[type=checkbox]');
		
		var list = protos.ul.clone();
		
		list.append(protos.li.clone().text('Select:'));

		var selectAll = protos.a.clone();
		selectAll.text('All').attr({'href':'#select-all'}).click(function(c) {
			c.preventDefault();
			checkboxes.attr({'checked':'checked'});
		});
		selectAll.appendTo(list).wrap(protos.li.clone());

		var selectNone = protos.a.clone();
		selectNone.text('None').attr({'href':'#select-none'}).click(function(c) {
			c.preventDefault();
			checkboxes.removeAttr('checked');
		});
		selectNone.appendTo(list).wrap(protos.li.clone());
		
		if( table.attr('summary') === 'inbox' ) {
			var selectRead = protos.a.clone();
			selectRead.text('Read').attr({'href':'#select-read'}).click(function(c) {
				c.preventDefault();
				checkboxes.removeAttr('checked').filter(function() { return $(this).parents('tr').find('.read').size(); }).attr({'checked':'checked'});
			});
			selectRead.appendTo(list).wrap(protos.li.clone());

			var selectUnread = protos.a.clone();
			selectUnread.text('Unread').attr({'href':'#select-unread'}).click(function(c) {
				c.preventDefault();
				checkboxes.removeAttr('checked').filter(function() { return $(this).parents('tr').find('.unread').size(); }).attr({'checked':'checked'});
			});
			selectUnread.appendTo(list).wrap(protos.li.clone());
		}
		
		list.appendTo(table.find('th.bulk-select'));
		
		var actions = table.find('th.bulk-actions input[type=radio]');
		actions.click(function() {
			form.submit();
		});
		form.find('button[type=submit]').parent('li').hide();
	};
	
	syncopate.typeaheadForms = function() {
		var inputs = $(':input[rel]').filter('[rel!=wysiwyg]').filter(':not(.target)');
		var searchUrl = '/search.json';
		if( ! inputs.size() ) { return; }
		var loader = null;
		
		inputs.each(function() {
			var target = $(this);
			target.hide();
			target.addClass('target');
			var resultsList = protos.typeahead.resultsUL.clone();
			target.parent().addClass('typeahead').append(resultsList).append(protos.clear.clone());
		 	var handleChoice = function() {
				syncopate.isTypeaheadEvent = true;
				var currentSelected = resultsList.children('li.selected');
				if ( ! currentSelected.size() ) {
					setTimeout(function() {
						handleChoice();
					},250);
					return;
				}
				switch(target.attr('type')) {
					case 'text':
						target.val(currentSelected.attr('rel'));
						break;
					default:
						switch(target[0].tagName.toLowerCase()) {
							case 'select':
								if( ! target.is('[multiple]') ) {
									target.find('option[selected]').removeAttr('selected');
								}
								var currentOpt = target.find('option[value=' + currentSelected.attr('rel') + ']');
								if( currentOpt.size() ) {
									currentOpt.attr({'selected':'selected'});
								} else {
									var newOpt = protos.option.clone();
									newOpt.attr({'selected':'selected', 'value': currentSelected.attr('rel')});
									target.append(newOpt);
								}
								break;
							default:
								// do nothing
						}
				}
				if( target.parent().find('span.typeahead-result[rel=' + currentSelected.attr('rel') + ']').size() ) { resultsList.children().remove(); input.val('').focus(); return; }
				var span = protos.typeahead.span.clone();
				span.text(currentSelected.text()).attr({'rel': currentSelected.attr('rel')});
				var remove = protos.typeahead.remove.clone();
				remove.click(function(c) {
					c.preventDefault();
					span.remove();
					switch(target.attr('type')) {
						case 'text':
							target.val('');
							input.width(fauxInput.width()).show().focus();
							break;
						default:
							switch(target[0].tagName.toLowerCase()) {
								case 'select':
									target.find('option[value=' + span.attr('rel') + ']').removeAttr('selected');
									break;
								default:
									// do nothing
							}
					}
				});
				span.append(remove);
				switch(target.attr('type')) {
					case 'text':
						input.before(span).val('');
						input.width(fauxInput.width() - span.outerWidth(true) - 10);
						input.attr({'disabled': 'disabled'});
						fauxInput.removeClass('focused');
					default:
						switch(target[0].tagName.toLowerCase()) {
							case 'select':
								fauxInput.after(span);
								input.val('').focus();
								break;
							default:
								// do nothing
						}
				}
				resultsList.children().remove();
			}
			var input = protos.typeahead.input.clone();
			var fauxInput = protos.typeahead.fauxInput.clone();
			if ( target.prev().size() ) {
				target.prev().after(fauxInput);
			} else if ( target.next().size() ) {
				target.next().before(fauxInput);
			} else {
				target.parent().append(fauxInput);
			}
			input.width(fauxInput.width()).height(fauxInput.height()).appendTo(fauxInput);
			input.focus(function() {
				fauxInput.addClass('focused');
			});
			input.blur(function() {
				setTimeout(function(){
					fauxInput.removeClass('focused');
					resultsList.children().remove();
				},100);
			});
			resultsList.css({ 'top': Math.ceil(fauxInput.position().top + fauxInput.outerHeight()) + 'px' });
			syncopate.isTypeaheadEvent = false;
			input.parents('form').submit(function(s) {
				s.stopPropagation();
				if( ( ! target.parents('.required').size() || ( target.val() && target.val() != '' ) ) && ! syncopate.isTypeaheadEvent) {
					return true;
				} else {
					syncopate.isTypeaheadEvent = false;
					return false;
				}
			});
			if( target.val() ) { // handle default vals
				var defaults = target.find('option[selected]');
				if( target.is('input') ) {
					defaults = defaults.add(target);
				}
				
				defaults.each(function() {
					var option = $(this);
					var span = protos.typeahead.span.clone();
					span.text( option.is('[rev]') ? unescape(option.attr('rev')) : option.text() ).attr({'rel': option.val()});
					var remove = protos.typeahead.remove.clone();
					remove.click(function(c) {
						c.preventDefault();
						span.remove();
						switch(target.attr('type')) {
							case 'text':
								target.val('');
								input.width(fauxInput.width()).show().focus();
								break;
							default:
								switch(target[0].tagName.toLowerCase()) {
									case 'select':
										target.find('option[value=' + span.attr('rel') + ']').removeAttr('selected');
										break;
									default:
										// do nothing
								}
						}
					});
					span.append(remove);
					switch(target.attr('type')) {
						case 'text':
							input.before(span).val('');
							input.width(fauxInput.width() - span.outerWidth(true) - 10);
							input.hide();
						default:
							switch(target[0].tagName.toLowerCase()) {
								case 'select':
									fauxInput.after(span);
									input.val('');
									break;
								default:
									// do nothing
							}
					}
				});
			}
			input.keydown(function(e) {
				e.stopPropagation();
				var pressed = e.which;
				switch( pressed ) {
					case 38: // Up arrow
						var currentSelected = resultsList.children('li.selected');
						currentSelected.removeClass('selected');
						if( currentSelected.size() && currentSelected.prev('li').size() ) {
							currentSelected.prev('li').addClass('selected');
						} else {
							resultsList.children(':last-child').addClass('selected');
						}
						break;
					case 40: // Down arrow
						var currentSelected = resultsList.children('li.selected');
						currentSelected.removeClass('selected');
						if( currentSelected.size() && currentSelected.next('li').size() ) {
							currentSelected.next('li').addClass('selected');
						} else {
							resultsList.children(':first-child').addClass('selected');
						}
						break;
					case 9: // Tab
					case 13: // Return
						handleChoice();
						break;
					case 27: // Escape
						input.val('');
						resultsList.children().remove();
						fauxInput.children('span').remove();
						if( target.is('input') ) {
							target.val('');
						}
						break;
					default: // string handling
						setTimeout(function(){
							if( input.val().length >= 3 ) { // ajax lookup
								$.getJSON(
									searchUrl,
									{'q': input.val()},
									function(json) {
										var currentSelected = resultsList.children('li.selected');
										resultsList.children('li').remove();
										if( json && ( typeof json.results == 'undefined' || json.results == 0 ) ) {
											resultsList.append(protos.typeahead.resultsLI.clone().html('No results found for &ldquo;' + input.val() + '&rdquo;'))
											return;
										}
										$.each( json.results.items, function() {
											try {
												var result = this;
												if( ! ( result.type == target.attr('rel') || ( result.is_group && target.attr('rel') == 'group' ) ) ) { return; }
												var li = protos.typeahead.resultsLI.clone();
												li.attr({'rel': result.pk}).text(result.name).appendTo(resultsList);
												if ( currentSelected.size() && li.attr('rel') == currentSelected.attr('rel') ) {
													li.addClass('selected');
												}
												li.click(function() {
													resultsList.children('.selected').removeClass('selected');
													li.addClass('selected');
													handleChoice();
												});
											} catch(e) { log(e); }
										});
										if( ! resultsList.children('li').size() ) {
											resultsList.append(protos.typeahead.resultsLI.clone().html('No results found for &ldquo;' + input.val() + '&rdquo;'))
										}
									}
								);
							} else {
								resultsList.children('li').remove();
							}
						},10);
				}
			});
		});
	}
	
	syncopate.audioPlayers = function() {
		$.fn.media.defaults.mp3Player = syncopate.S3_STORAGE_URL + 'player.swf';
		syncopate.audio = null;
		syncopate.newAudio = null;
		syncopate.inlineAudio = null;
		var fader = null;
		if( syncopate.playerWindow ) {
			syncopate.audio = syncopate.playerWindow.syncopate.audio;
			syncopate.newAudio = syncopate.playerWindow.syncopate.newAudio;
		}
		function ImprovedAudio(src) {
			if( !!(document.createElement('audio').canPlayType('audio/mpeg')) ) {
				return new Audio(src);
			} else {
				var randomNumber = Math.floor(Math.random()*100001);
				$('body').append($('<div id="flash-player-holder-' + randomNumber + '" class="flash-dummy" />'));
				$f('flash-player-holder-' + randomNumber, 'http://media.syncopate.me/js/flowplayer-3.1.3.swf', {
					'plugins': {
						'controls': null,
						'audio': {
							'url': 'http://media.syncopate.me/js/flowplayer.audio-3.1.0.swf'
						}
					},
					'clip': {
						'autoPlay': false,
						'url': src,
						'onFinish': function() {
						},
						'onLastSecond': function() {
							_audio.ended = true;
							$(_audio).trigger('ended');
						},
						'onBegin': function() {
						}
					}
				});
				this.audio = $f('flash-player-holder-' + randomNumber);
			}
			var _audio = this.audio;

			_audio.setAttribute = function(attr, val) {
				if( attr == 'volume' && typeof _audio.setVolume != 'undefined' ) {
					_audio.setVolume( val * 100 );
				} else {
					_audio[attr] = val;
				}
			}

			_audio.getAttribute = function(attr) {
				if( attr == 'src' && typeof _audio.getClip != 'undefined' ) {
					return _audio.getClip(0).completeUrl;
				}
				return _audio[attr];
			}

			if( typeof randomNumber != 'undefined' ) { // We're dealing with flash here

				_audio.ended = false;

				_audio.volume = false;
			}

			return _audio;
		}
		if( $('body.playlist, body.playlists').size() ) {
			var playlists = $('.playlist');
			if( $.browser.mobile ) {
				playlists.hide().eq(0).show();
				playlists.each(function() {
					var playlist = $(this);
					var songs = playlist.find('.songs a.play');
					var firstSong = playlist.find('.songs li:first-child a.play');
					var embed = protos.embed.clone()[0];
					embed.target = 'myself';
					embed.autoplay = 'false';
					embed.src = firstSong.attr('href');
					embed.loop = 'false';
					embed.controller = 'false';
					embed.title = $('#main > h1').text();
					songs.each(function(index) {
						if( ! index ) { return; }
						embed.setAttribute('qtnext' + (index), '<' + $(this).attr('href') + '>T<myself>');
					});
					playlist.find('.player').append($(embed));
					$(embed).click();
				});
			} else {
				var currentPlaylist = null;
				var isPlaying = false;
				playlists.each(function() {
					var playlist = $(this);
					var songs = playlist.find('.songs li');
					var list = playlist.find('ul.songs');
					var links = songs.find('a.play');
					var holder = playlist.find('ul.tabs');
					var dur = holder.find('.duration').size() ? holder.find('.duration') :  protos.span.clone().addClass('duration').text('-:--');
					var cur = holder.find('.duration').size() ? holder.find('.duration') : protos.span.clone().addClass('current-time').text('-:--');
					var progressBar = holder.find('.progress-bar').size() ? holder.find('.progress-bar') : protos.span.clone().addClass('progress-bar').appendTo(holder.find(".player")).before(cur).after(dur);;
					var progressIndicator = holder.find('.indicator').size() ? holder.find('.indicator') : protos.span.clone().addClass('indicator').appendTo(progressBar);
					var formatTime = function(time) {
						if( isNaN(time) ) { return "-:--"; }
						time = Math.round(time);
						var result = time;
						if( time < 10 ) {
							result = '0:0' + time;
						} else if( time < 60 ) {
							result = '0:' + time;
						} else {
							minutes = String(Math.floor( time / 60 ));
							remainder = time % 60;
							result = minutes;
							result += ':';
							result += (remainder < 10) ? '0' + String(remainder) : String(remainder);
						}
						return result;
					}
					var updateProgress = function(audio) {
						try {
							if( audio.currentTime == undefined ) {
								$('.player').slideUp('normal');
								holder.css({'padding-bottom': 0});
								clearInterval(updater);
							}
							if( currentPlaylist != playlist.attr('id') ) {
								progressIndicator.css({'width': 0});
								dur.text('-:--');
								cur.text('-:--');
								return;
							}
							progressIndicator.css({'width': ((audio.currentTime / audio.duration) * 100) + '%' });
							dur.text(formatTime(audio.duration));
							cur.text(formatTime(audio.currentTime));
						} catch(e) {}
					}
					var updater = null;
					var playNext = function() {
						if( currentPlaylist != playlist.attr('id') ) {
							links.eq(0).click();
							return;
						}
						try{
							currentSong = links.filter('[href=' + syncopate.audio.getAttribute('src').replace(syncopate.ROOTURL,'') + ']');
							currentSong.parent('li').next('li').size() ? currentSong.parent('li').next('li').find('a.play').click() : currentSong.parent('li').siblings('li:first-child').find('a.play').click();
						}catch(e) {}
					};
					var playPrevious = function() {
						if( currentPlaylist != playlist.attr('id') ) {
							links.eq(links.size() - 1).click();
							return;
						}
						try{
							currentSong = links.filter('[href=' + syncopate.audio.getAttribute('src').replace(syncopate.ROOTURL,'') + ']');
							currentSong.parent('li').prev('li').size() ? currentSong.parent('li').prev('li').find('a.play').click() : currentSong.parent('li').siblings('li:last-child').find('a.play').click();
						}catch(e){}
					};
					var next = holder.find('.next').size() ? holder.find('.next') : protos.a.clone().attr({'href': '#next', 'title': 'Play next song'}).html('Next &raquo;').addClass('next').prependTo(holder).wrap(protos.li.clone().addClass('button')).click(function(c) {
						c.preventDefault();
						playNext();
					});
					var playPause = holder.find('.playpause').size() ? holder.find('.playpause') : protos.a.clone().attr({'href': '#play', 'title': 'Play'}).html('Play').addClass('playpause').addClass('play').prependTo(holder).wrap(protos.li.clone().addClass('button playpause')).click(function(c) {
						c.preventDefault();
						if( playPause.is('.play') ) {
							if( isPlaying && currentPlaylist != playlist.attr('id') ) {
								if( fader ) {
									clearInterval(fader);
									if( syncopate.newAudio ) {
										syncopate.audio = syncopate.newAudio;
									}
								}
								playlist.siblings('.playlist').find('.pause').click();
								playNext();
								return;
							}
							if( ! syncopate.audio ) {
								playNext();
								return;
							} else {
								syncopate.audio.play();
								isPlaying = true;
							}
							playlist.siblings('.playlist').find('.playpause').attr({'href': '#play', 'title':'Play'}).html('Play').removeClass('pause').addClass('play');
							playPause.attr({'href': '#pause', 'title':'Pause'}).html('Pause').removeClass('play').addClass('pause');
						} else {
							if( (syncopate.audio || syncopate.newAudio) && currentPlaylist != playlist.attr('id') ) {
								return;
							}
							if( ! syncopate.audio ) {
								playPrevious();
								return;
							} else {
								syncopate.audio.pause();
								isPlaying = false;
							}
							if( syncopate.newAudio ) {
								syncopate.newAudio.pause();
								syncopate.audio = syncopate.newAudio;
							}
							syncopate.audio.pause();
							playPause.attr({'href': '#play', 'title':'Play'}).html('Play').removeClass('pause').addClass('play');
						}
					});
					var prev = holder.find('.prev').size() ? holder.find('.prev') : protos.a.clone().attr({'href': '#previous', 'title': 'Play previous song'}).html('&laquo; Previous').addClass('prev').prependTo(holder).wrap(protos.li.clone().addClass('button')).click(function(c) {
						c.preventDefault();
						playPrevious();
					});
					links.each(function() {
						var song = $(this);
						if( ! song.is(':visible') ) { playNext(); }
						song.unbind('click');
						song.click(function(c) {
							c.preventDefault();
							clearInterval(updater);
							currentPlaylist = playlist.attr('id');
							playlist.siblings('.playlist').find('.playpause').attr({'href': '#play', 'title':'Play'}).html('Play').removeClass('pause').addClass('play');
							playPause.attr({'href': '#pause', 'title':'Pause'}).html('Pause').removeClass('play').addClass('pause');
							progressIndicator.css({'width': 0});
							
							if(self.opener && typeof self.opener.window.syncopate != 'undefined' && self.opener.window.syncopate.inlineAudio) {
								self.opener.window.syncopate.inlineAudio.pause();
								self.opener.window.syncopate.inlineAudio = null;
							}
							
							syncopate.newAudio = new ImprovedAudio(song.attr('href'));
							syncopate.newAudio.setAttribute('autoplay', 'autoplay');
							syncopate.newAudio.play();
							isPlaying = true;
							if( ! syncopate.audio || syncopate.audio.getAttribute('ended') ) {
								if( syncopate.audio ) { syncopate.audio.pause() };
								syncopate.newAudio.setAttribute('volume', syncopate.audio ? syncopate.audio.volume : 1);
								$(syncopate.newAudio).bind('ended', function() {
									playNext();
								});
								try {
									$(syncopate.audio.getParent()).remove();
								} catch(e) {}
								syncopate.audio = syncopate.newAudio;
								syncopate.newAudio = null;
								updater = setInterval(function(){
									updateProgress(syncopate.audio);
								},250);
							} else {
								syncopate.newAudio.setAttribute('volume', 0);
								$(syncopate.newAudio).bind('ended', function() {
									playNext();
								});
								updater = setInterval(function(){
									updateProgress(syncopate.newAudio);
								},250);
								if( syncopate.audio.volume ) {
									fader = setInterval(function(){
										try {
											syncopate.audio.volume -= 0.05;
										} catch(e) {
											syncopate.audio.volume = 0;
										}
										try {
											syncopate.newAudio.volume += 0.05;
										} catch(e) {
											syncopate.newAudio.volume = 1;
										}
										if( syncopate.audio.volume == 0 && syncopate.newAudio.volume == 1 ) {
											clearInterval(fader);
											try {
												$(syncopate.audio.getParent()).remove();
											} catch(e) {}
											syncopate.audio.pause();
											syncopate.audio = syncopate.newAudio;
											syncopate.newAudio = null;
										}
									},100);
								} else {
									try {
										$(syncopate.audio.getParent()).remove();
									} catch(e) {}
									syncopate.audio = syncopate.newAudio;
									syncopate.newAudio = null;
								}
							}

							var parent = song.parent('li');
							$('.songs li.selected').removeClass('selected');
							if ( parent.is(':last-child') ) { // we've clicked previous
								parent.prependTo(list);
							} else if( parent.is(':first-child') ) {
								parent.prevAll('li').appendTo(list);
								parent.prependTo(list);
							} else {
								parent.add(parent.nextAll('li')).add($.makeArray(parent.prevAll('li')).reverse()).prependTo(list);
							}
							parent.addClass('selected');
						});
					});
				});
			}
		} else {
			var links = $('a.play');
			links.click(function(c) {
				c.preventDefault();
				var link = $(this);
				if( syncopate.playerWindow && typeof syncopate.playerWindow.syncopate != 'undefined' ) {
					syncopate.audio = syncopate.playerWindow.syncopate.audio;
					syncopate.newAudio = syncopate.playerWindow.syncopate.newAudio;
				}
				if( syncopate.audio ) {
					syncopate.audio.pause();
				}
				if( syncopate.newAudio ) {
					syncopate.newAudio.pause();
					syncopate.audio = syncopate.newAudio;
					syncopate.newAudio = null;
				}
				if( link.is('.stop') ) {
					link.removeClass('stop');
					syncopate.inlineAudio.pause();
					syncopate.inlineAudio = null;
					if( syncopate.audio ) {
						setTimeout(function() {
							if( syncopate.audio.volume ) {
								syncopate.audio.volume = 0;
							}
							syncopate.audio.play();
							if( syncopate.audio.volume === 0 ) {
								fader = setInterval(function(){
									try {
										syncopate.audio.volume += 0.05;
									} catch(e) {
										syncopate.audio.volume = 1;
									}
									if( syncopate.audio.volume == 1 ) {
										clearInterval(fader);
									}
								},100);
							}
						}, 500);
					}
				} else {
					if( syncopate.inlineAudio ) {
						syncopate.inlineAudio.pause();
					}
					syncopate.inlineAudio = new ImprovedAudio(link.attr('href'));
					syncopate.inlineAudio.play();
					link.addClass('stop');
				}
			});

			var audios = $('audio');
			var dimensions = {
				'height': 18
			}
			if ( ! audios.size() || audioIsNative ) { return; }
			audios.each(function() {
				var audio = $(this);
				var link = protos.a.clone().attr({'title': audio.attr('title'), 'href': audio.attr('src') }).text(audio.attr('title'));
				audio.replaceWith(link);
				if ( audio.parents('#sb').size() ) {
					dimensions.width = 300
				} else {
					dimensions.width = 603
				}
				link.media({'autoplay': false, 'caption': false, 'width': dimensions.width, 'height': dimensions.height, 'attrs': {'flashVars': 'type=sound&backcolor=#000000&frontcolor=#d4d4d4&lightcolor=#ffffff'}});
			});
		}
	}
	
	syncopate.maps = function() {
		var maps = $('.map');
		syncopate.geocoder = new google.maps.Geocoder() // Init the geocoder
		if ( ! syncopate.geocoder ) { return false; } // bail, none of this will work
		maps.each(function() {
			var mapWidget = $(this);
			var mapHolder = protos.mapHolder.clone();
			mapHolder.prependTo(mapWidget);
			syncopate.geocoder.geocode(
				{ 'address': unescape( mapWidget.attr('data-address') ) },
				function( results, status ) {
					if ( status != google.maps.GeocoderStatus.OK ) { return; }
					var map = new google.maps.Map(mapHolder[0], {
						'zoom': 8,
						'center': results[0].geometry.location,
						'mapTypeId': google.maps.MapTypeId.ROADMAP,
						'scrollwheel': false,
						'disableDefaultUI': true,
						'navigationControl': true
					}); // Set up the map
					map.fitBounds( results[0].geometry.viewport );
					var marker = new google.maps.Marker({
						'map': map,
						'position': results[0].geometry.location
					});
				}
			);
		});
	}
	
	syncopate.like = function() {
		var links = $('.tabs .like a, a.like');
		var loading = protos.img.clone().attr({'src': 'http://media.syncopate.me/images/dashboard-loading.gif'});
		links.click(function(c) {
			c.preventDefault();
			var link = $(this);
			var linkText = link.text();
			if( link.is('.like') ) {
				link.css({
					'background-image': loading.attr('src')
				});
			} else {
				link.html(loading.clone());
			}
			$.ajax({
				'complete': function(data) {
					link.removeAttr('style');
					link.html(linkText);
					if( ! $('#bd ul.messages').size() ) {
						$('#bd').prepend(protos.ul.clone().addClass('messages'));
					}
					$('#bd ul.messages').append(protos.li.clone().text(data.responseText));
					syncopate.feedback();
				},
				'error': function() {
					syncopate.alert('Sorry, there was an error.');
				},
				'global': false,
				'success': function() {
					var counter = link.parents('.widget').find('.like-count');
					if( link.is('.like') ) {
						var linkParent = link.parent();
						link.removeClass('like').addClass('liked');
						if( $.trim( linkParent.html() ) == '' ) {
							linkParent.remove();
						}
					} else {
						link.parent('.like').remove();
					}
					var current_count = apnumber_reverse( counter.text() );
					counter.text( intcomma( apnumber( current_count + 1 ) ) );
					if ( current_count === 1 ) {
						counter.parent('p').html($.trim(counter.parent('p').html()) + 's');
					}
				},
				'url': link.attr('href')
			});
		});
	}
	
	syncopate.addToPlaylist = function() {
		var overlay = $('#overlay').size() ? $('#overlay') : protos.div.clone().attr({'id': 'overlay'}).css({'display': 'none'});
		var formHolderWrapper = protos.div.clone().attr({'id': 'form-holder'}).css({'display': 'none'});
		var formHolder = protos.div.clone().addClass('target');
		overlay.click(function() {
			formHolderWrapper.hide();
			formHolder.empty();
		});
		formHolder.click(function(c) {
			c.stopPropagation();
		});
		var ajaxTemp = protos.div.clone();
		formHolder.appendTo(formHolderWrapper.appendTo($('body')));
		var close = protos.a.clone().attr({'href': '#close'}).addClass('close').html('&times; Close');
		close.appendTo(formHolderWrapper).click(function(c) {
			c.preventDefault();
			formHolderWrapper.add(overlay).hide();
		});
		var links = $('a.playlist, a.add-all');
		links.click(function(c) {
			c.preventDefault();
			var link = $(this);
			overlay.show();
			formHolder.empty();
			formHolderWrapper.show().addClass('loading');
			ajaxTemp.load(link.attr('href').split('?')[0],
				function(){
					formHolderWrapper.removeClass('loading');
					formHolder.append(ajaxTemp.find('#main h1'));
					var form = ajaxTemp.find('#main form');
					form.find('button[value=add],button[value=continue]').remove();
					setTimeout(function(){
						$('form .date input').datepicker();
						syncopate.feedback();
						syncopate.timepicker();
						syncopate.typeaheadForms();
						try {
							$('textarea[rel=wysiwyg]').wysiwyg({'css':$('link[rel=stylesheet][href$=syncopate.css]').attr('href').replace('syncopate.css','wysiwyg-overrides.css')});
						} catch(e) { /* do nothing */ }
					},10);
					formHolder.prepend(ajaxTemp.find('.widget.photo-preview img'));
					ajaxTemp.empty();
					form.ajaxForm({
						'beforeSubmit': function() {
							if( syncopate.isTypeaheadEvent ) {
								return false;
							}
							form.hide();
							formHolderWrapper.addClass('loading');
							formHolder.find('ul.messages,ul.errors').remove();
						},
						'success': function(responseText) {
							var response = $(responseText);
							formHolderWrapper.removeClass('loading');
							syncopate.notifiers(response.find('ul.messages,ul.errors'));
							overlay.add(formHolderWrapper).hide();
							formHolder.empty();
							syncopate.feedback();
							var updatedPlaylist = response.find('[id^=playlist-]');
							if( updatedPlaylist.size() ) {
								try {
									var oldPlaylist = $(syncopate.playerWindow.document).find('#' + updatedPlaylist.attr('id'));
									if( oldPlaylist.size() ) {
										if( oldPlaylist.find('li.selected').size() ) {
											updatedPlaylist.find('li#' + oldPlaylist.find('li.selected').attr('id')).addClass('selected');
										}
										oldPlaylist.find('ul.songs').replaceWith(updatedPlaylist.find('ul.songs')).remove();
									} else {
										$(syncopate.playerWindow.document).find('#main h1').after(updatedPlaylist.before(updatedPlaylist.prev('h2')));
									}
									setTimeout(function(){
										syncopate.audioPlayers();
									},100);
								} catch(e) {}
							}
						},
						'url': link.attr('href').split('?')[0]
					});
					formHolder.append(form);
				}
			);
		});
	}
	
	syncopate.relativeDates = function() {
	    var now = Date.parse(new Date());

	    $('abbr.datetime').each(function() {
	      var span = $(this);
	      var timestamp = Date.parse(span.attr('title'));
	      var diff = now - timestamp;
	      var nicetext = "";
	      time = {};
	      time.year =   Math.floor( diff / 31536000000 ); // 365 time.day. Fuck leap year.;
	      time.month =  Math.floor( ( diff - ( time.year * 31536000000 ) ) / 2592000000 ); // Assuming a month is 30 time.day. Close enough.;
	      time.week =   Math.floor( ( diff - ( time.year * 31536000000 ) - ( time.month * 2592000000 ) ) / 604800000 );
	      time.day =    Math.floor( ( diff - ( time.year * 31536000000 ) - ( time.month * 2592000000 ) - ( time.week * 604800000 ) ) / 86400000 );
	      time.hour =   Math.floor( ( diff - ( time.year * 31536000000 ) - ( time.month * 2592000000 ) - ( time.week * 604800000 ) - ( time.day * 86400000 ) ) / 3600000);
	      time.minute = Math.round( ( diff - ( time.year * 31536000000 ) - ( time.month * 2592000000 ) - ( time.week * 604800000 ) - ( time.day * 86400000 ) - ( time.hour * 3600000 ) ) / 60000 );

	      for(var key in time) {
	        if(time[key] > 0) {
	          switch(key) {
	            case 'minute':
	              if ( time.month > 0 || time.year > 0  || time.hour > 12 || time.week > 0 || time.day > 0 ) { continue; }
	            case 'hour':
	              if( time.week > 0 || time.month > 0 || time.year > 0 ) { continue; }
	            case 'day':
	              if( time.year > 0 || ( time.week > 0 && time.month > 0 ) ) { continue; }
	            default:
	              // keep going
	          }
	          nicetext = nicetext + " " + time[key] + " " + key + (time[key] > 1 ? "s," : ",");
	        }
	      }
	      if(diff <= 30000) {
	        nicetext = "now"
	      } else if(nicetext == "") {
	        nicetext = span.text();
	      } else {
	        nicetext = nicetext.substr(0,nicetext.length - 1) + " ago";
	      }

	      span.text(nicetext);
	    });
	}
	
	syncopate.player = function() {
		try {
			self.opener.window.syncopate.playerWindow = self;
		}catch(e){}
		if ( self.opener ) {
			setInterval( function() {
				try {
					self.opener.window.syncopate.playerWindow = self;
				}catch(e){}
			}, 250);
		}
		$('header .player a').click(function(c) {
			c.preventDefault();
			if( syncopate.playerWindow && ! syncopate.playerWindow.closed ) {
				syncopate.playerWindow.focus();
			} else {
				syncopate.playerWindow = window.open( $(this).attr('href') + '?popup=true', 'player', 'width=320,height=480,toolbar=no,location=no,status=no,menubar=no,copyhistory=no' );
			}
		});
		if( $('body').is('scripted') ) { return; }
		$('body').addClass('scripted');
		var playlists = $('.widget.playlist');
		var headers = playlists.prev('h2');
		lists = $('thistagdoesntexist');
		playlists.each(function(index) {
			var playlist = $(this);
			var list = protos.ul.clone().addClass('playlist-choices').hide();
			var manage = protos.ul.clone().addClass('playlist-manage').hide();
			lists = lists.add(list);
			var button = $('<a />');
			button.attr({'href': '#choose-playlist', 'title': 'Choose playlist'}).text('Playlists');
			var currentPlaylist = protos.a.clone().text($.trim(playlist.prev('h2').text())).addClass('current-playlist').attr({'href': '#manage-playlist', 'title': 'Click to Manage this Playlist'}).click(function(c) {
				c.preventDefault();
				if(manage.is(':visible')) {
					manage.fadeOut(250);
				} else {
					manage.show();
				}
				lists.fadeOut(250);
			});
			var remove = protos.a.clone().attr({'href': '#remove-songs', 'title': 'Remove Songs from this Playlist'}).text('Remove Songs').click(function(c) {
				c.preventDefault();
				if( remove.is('.on') ) {
					remove.removeClass('on');
					playlist.removeClass('remove-songs');
					manage.fadeOut(250, function() {
						remove.text('Remove Songs');
					});
				} else {
					remove.text('Finished Removing').addClass('on');
					playlist.addClass('remove-songs');
				}
			});
			remove.appendTo(manage).wrap(protos.li.clone());
			var subTabs = protos.ul.clone();
			subTabs.addClass('sub-tabs')
			subTabs.append(currentPlaylist);
			currentPlaylist.wrap(protos.li.clone());
			currentPlaylist.after(manage);
			button.bind('click',function(c) {
				c.preventDefault();
				if(list.is(':visible')) {
					lists.fadeOut(250);
				} else {
					lists.show();
				}
				manage.fadeOut(250);
			});
			subTabs.append(button);
			button.wrap('<li />');
			playlist.find('.tabs').after(subTabs);
			headers.each(function() {
				var header = $(this);
				list.append(protos.li.clone().append(protos.a.clone().text($.trim(header.text())).attr({'href': '#' + header.next('.playlist').attr('id'), 'title': $.trim(header.text())}).click(function(c) {
					c.preventDefault();
					var toPlaylist = playlists.filter('[id=' + $(this).attr('href').replace('#', '') + ']');
					lists.hide();
					if ( toPlaylist.attr('id') == playlist.attr('id') ) { return; }
					toPlaylist.show();
					toPlaylist.siblings('.playlist').hide();
				})));
			});
			button.parent().append(list);
		});
		playlists.hide().eq(0).show();
		headers.remove();
		
		var removes = $('.playlist a.playlist-remove');
		removes.live('click', function(c) {
			c.preventDefault();
			var del = $(this);
			syncopate.confirm("Are you sure you want to remove " + $.trim(del.siblings('.title').text()) + " from " + del.parents('.playlist').find('.current-playlist').text() + "?", function() {
				del.addClass('loading');
				$.ajax({
					'url': del.attr('href').split('?')[0],
					'type': 'POST',
					'dataType': 'html',
					'complete': function() {
						del.removeClass('loading');
					},
					'success': function() {
						del.parent('li').remove();
					},
					'error': function() {
						syncopate.alert($.trim(del.siblings('.title').text()) + " could not be removed.");
					}
				});
			});
		});
	}
	
	syncopate.confirm = function(text, positiveCallback, negativeCallback) {
		if( $.browser.mobile ) {
			if ( confirm( text ) ) {
				try {
					positiveCallback();
				} catch(e) {}
			} else {
				try {
					negativeCallback();
				} catch(e) {}
			}
			return;
		}
		var notifiers = $('#notifiers').size() ? $('#notifiers') : protos.table.clone().attr({'id': 'notifiers'}).css({'display': 'notifiers'}).append(protos.tr.clone().append(protos.td.clone())).appendTo($('body'));
		notifiers.show();
		var confirm = protos.div.clone().append('<p>' + text + '</p>').addClass('confirm');
		var cancel = protos.button.clone().text('Cancel').bind("click keydown", function(c) {
			if ( ( c.type == 'keycode' && c.which == 13 ) || c.type == 'click' ) {
				c.preventDefault();
				confirm.fadeOut(250, function() {
					if( ! notifiers.find('td').children().size() ) {
						notifiers.hide();
					}
				});
				try {
					negativeCallback();
				} catch(e) {}
			}
		});
		var ok = protos.button.clone().text('OK').bind("click keydown", function(c) {
			if ( ( c.type == 'keycode' && c.which == 13 ) || c.type == 'click' ) {
				c.preventDefault();
				notifiers.hide();
				confirm.fadeOut(250, function() {
					if( ! notifiers.find('td').children().size() ) {
						notifiers.hide();
					}
				});
				try {
					positiveCallback();
				} catch(e) {}
			}
		});
		confirm.append(protos.p.clone().addClass('right').addClass('buttons').append(cancel).append(ok)).appendTo(notifiers.find('td'));
		ok.focus();
		return confirm;
	}
	
	syncopate.alert = function(text, isNotify) {
		if( $.browser.mobile ) {
			alert( text );
			return;
		}
		var notifiers = $('#notifiers').size() ? $('#notifiers') : protos.table.clone().attr({'id': 'notifiers'}).css({'display': 'notifiers'}).append(protos.tr.clone().append(protos.td.clone())).appendTo($('body'));
		notifiers.addClass('transparent').show();
		var alert = protos.div.clone().append('<p>' + text + '</p>').addClass('alert');
		var ok = protos.button.clone().text('OK').bind("click keydown", function(c) {
			if ( ( c.type == 'keycode' && c.which == 13 ) || c.type == 'click' ) {
				c.preventDefault();
				alert.fadeOut(250, function() {
					alert.remove();
					if( ! notifiers.find('td').children().size() ) {
						notifiers.hide();
					}
				});
			}
		});
		alert.append(protos.p.clone().addClass('right').addClass('buttons').append(ok)).appendTo(notifiers.find('td'));
		ok.focus();
		if( isNotify ) {
			setTimeout(function() {
				ok.click();
			},5000);
		}
		return alert;
	}
	
	syncopate.notify = function(text) {
		return syncopate.alert(text, true)
	}
	
	syncopate.notifiers = function(lists) {
		lists.find('li').each(function() {
			var notifier = syncopate.notify($(this).text());
			if ( $(this).parent('.errorlist').size() ) {
				notifier.addClass('error');
			}
		});
	}
	
	syncopate.geolocate = function(force_update) {
		if($.cookie('latitude') && $.cookie('latitude') && ! force_update) {
			return {'latitude': $.cookie('latitude'), 'longitude': $.cookie('longitude')};
		}
		var coords = {'latitude': null, 'longitude': null};
		if( navigator.geolocation ) {
			navigator.geolocation.getCurrentPosition(function(position){
				coords.latitude = position.coords.latitude;
				coords.longitude = position.coords.longitude;
			});
		} else if( google.loader.ClientLocation ) {
			coords.latitude = google.loader.ClientLocation.latitude;
			coords.longitude = google.loader.ClientLocation.longitude;
		}
		$.cookie('latitude', coords.latitude, { 'expires': 1 });
		$.cookie('longitude', coords.longitude, { 'expires': 1 });
		return coords;
	}
})(jQuery);