jQuery.cookie=function(name,value,options){if(typeof value!='undefined'){options=options||{};if(value===null){value='';options.expires=-1;}
var expires='';if(options.expires&&(typeof options.expires=='number'||options.expires.toUTCString)){var date;if(typeof options.expires=='number'){date=new Date();date.setTime(date.getTime()+(options.expires*24*60*60*1000));}else{date=options.expires;}
expires='; expires='+date.toUTCString();}
var path=options.path?'; path='+(options.path):'';var domain=options.domain?'; domain='+(options.domain):'';var secure=options.secure?'; secure':'';document.cookie=[name,'=',encodeURIComponent(value),expires,path,domain,secure].join('');}else{var cookieValue=null;if(document.cookie&&document.cookie!=''){var cookies=document.cookie.split(';');for(var i=0;i<cookies.length;i++){var cookie=jQuery.trim(cookies[i]);if(cookie.substring(0,name.length+1)==(name+'=')){cookieValue=decodeURIComponent(cookie.substring(name.length+1));break;}}}
return cookieValue;}};

//TODO: Remove this before going live and any console stuff
// Fake Firebug in IE
if (!('console' in window) || !('firebug' in console)) {
	var names = ['log', 'debug', 'info', 'warn', 'error', 'assert', 'dir', 'dirxml', 'group', 'groupEnd', 'time', 'timeEnd', 'count', 'trace', 'profile', 'profileEnd'];
	window.console = {};
	for (var i = 0; i < names.length; ++i) {
		window.console[names[i]] = function() {};
	}
}

var cookie =
{
	name: 'youversion',
	expires: 365,

	get: function()
	{
		return $.cookie(this.name);
	},

	set: function(object, data)
	{
		var new_cookie = this.get();

		if (new_cookie === null)
		{
			new_cookie = {
				interfaces: {
					www: {},
					iphone: {},
					blackberry: {},
					mobile: {}
				}
			};
		}
		else
		{
			new_cookie = $.evalJSON(new_cookie);
		}

		new_cookie.interfaces.www[object] = data;

		$.cookie(this.name, $.toJSON(new_cookie), {expires: this.expires});
	}
}

function setUndefinedValue(variable, default_value) {
	
	return (typeof(variable) === 'undefined') ? default_value : variable;
}

Array.prototype.compare = function(testArr) {
    if (this.length != testArr.length) return false;
    for (var i = 0; i < testArr.length; i++) {
        if (this[i].compare) { 
            if (!this[i].compare(testArr[i])) return false;
        }
        if (this[i] !== testArr[i]) return false;
    }
    return true;
}

String.prototype.limit_words = function(limit, endChar) {

	var longDescription = this;

	//limit = (typeof(limit) === 'undefined') ? 100 : limit;
	limit = setUndefinedValue(limit, 100);

	if (longDescription.length > limit) {
		//endChar = (typeof(endChar) === 'undefined') ? '&#8230;' : endChar;
		endChar = setUndefinedValue(endChar, '&#8230;');
		
		description = longDescription.substring(0, limit);
		description = description.replace(/\w+$/, '');
		description += endChar;
		
		return description;
	}
	
	return longDescription;
}

var search_boxes = false;

$(function() {

	// External links
	$('a[rel*="external"]').live('click', function() {
        window.open($(this).attr('href'));
        return false;
    });

	// Report links
	$('li.report > a, a.report').live('click', function(event) {
		var confirmation = confirm('Are you sure you want to report this?');

		if (confirmation === false) {
			event.preventDefault();
		}
	});

	var search_box_focus = function() {
		var el = $(this);
		if (el.hasClass('placeholder')) {
			if (this.value === this.title) {
				this.value = '';
				el.removeClass('placeholder');
			}
		}
	};

	var search_box_blur = function() {
		if (this.value === '') {
			this.value = this.title;
			$(this).addClass('placeholder');
		}
	};

	// Search placeholder
	search_boxes = $('div.search-box input.search');
	search_boxes.focus(search_box_focus);
	search_boxes.blur(search_box_blur);

	// Add placeholder on load if empty
	$.each(search_boxes, function() {
		if (this.value === '' || this.value === this.title) {
			this.value = this.title;
			$(this).addClass('placeholder');
		}
	});

	// Prevent submit of empty value
	$('div.search-box form').submit(function(e) {
		var search_field = $(this).find('input.search');

		if (search_field.val() === search_field.attr('title') || search_field.val() === '') {
			e.preventDefault();
		}
	});

	// Load in Google Analytics dynamically, only in production
	if (IN_PRODUCTION === true) {
		$(window).load(loadGA);
	}
});

String.prototype.osis_to_human = function() {
	// TODO: Make this function accept which pane they are in so we use correct book list
	var osis = this.split(/[._]/);
	
	if (typeof(reader.main.books.osis_to_human[osis[0]]) !== 'undefined') {
		if (osis.length === 3) {
			return reader.main.books.osis_to_human[osis[0]][0] + ' ' + osis[1] + ':' + osis[2];
		} else if (osis.length === 2) {
			return reader.main.books.osis_to_human[osis[0]][0] + ' ' + osis[1];
		}
	}

	return false;
}

String.prototype.human_to_osis = function(book_human_to_osis, separator, allow_range) {
	var reference = this;
	var reference_original = reference;

	separator = (typeof(separator) === 'undefined') ? '.' : separator;
	allow_range = (typeof(allow_range) === 'undefined') ? false : allow_range;

	// Adjust Song of Solomon
	reference = reference.replace(/(Song of Solomon|Song of Soloman|Song of Songs)/i, 'Song');

	var regexp = /((?:[1-3] )?(?:.*?)) (?:(\d{1,3})(?::(\d{1,3})(?:-(\d{1,3}))?)?)?/;
	
	reference = reference.match(regexp);

	if (reference !== null && typeof(reference[1]) !== 'undefined' && typeof(reference[2]) !== 'undefined') {

		if (reference[1] === 'Song') {
			reference[1] = 'Song of Solomon';
		}

		var book = reference[1].uc_first();

		var chapter = Number(reference[2]);
		chapter = (chapter > 0) ? chapter : 1;

		var verse = Number(reference[3]);
		verse = (verse > 0) ? verse : false;
		
		var range = Number(reference[4]);
		range = (range > 0) ? range : false;

	} else if (reference_original.length > 0) {
		var book = reference_original.replace(/^\s+|\s+$/g, '');
		var chapter = 1;
		var verse   = false;
	} else {
		return false;
	}

	// See if book is valid
	if (typeof(book_human_to_osis[book]) !== 'undefined') {
		book = book_human_to_osis[book][0];
	} else {
		return false;
	}

	if (verse === false) {
		return book + separator + chapter;
	} else if (range === false || allow_range === false) {
		return book + separator + chapter + separator + verse;
	} else {
		return book + separator + chapter + separator + verse + '-' + range;
	}
}

String.prototype.uc_first = function (i) {

	// Determine if first is numeric
	var fchar = this.substr(0,1);

	if (fchar == parseInt(fchar)) {
		return this.substr(0,1) + this.substr(1,1).toUpperCase() + this.substr(2);
	}
	
	return this.substr(0,1).toUpperCase() + this.substr(1);
}

String.prototype.join = function(obj) {
	var out = "";
	
	for (val in obj)
	{
		out += "," + val;
	}
	
	return out.substring(1);
}

// Reference Suggest

var ref_suggest = {
	input: undefined,
	hidden: undefined,
	selectedItem: false,
	references: {},
	
	init: function(input, hidden, initial_values, results_name, callbacks) {

		results_name = (results_name || 'main');

		ref_suggest.input = $(input);
		ref_suggest.hidden = $(hidden);

		ref_suggest.input.unbind();
		ref_suggest.hidden.unbind();

		ref_suggest.input.bind('blur.ref_suggest', function(e) {
			ref_suggest.deselect();
		});

		ref_suggest.references = {};
		ref_suggest.input.parents('ul.reference_suggest').find('li:not(.input)').remove();

		ref_suggest.addValues(initial_values || "");

		ref_suggest.input.reference_suggest(
			results_name,
			{onSelect: function() {}}
		);

		// I really hate browser detection, but I don't see any other way
		if ($.browser.mozilla)
		{
			ref_suggest.input.keypress(ref_suggest.processKey);	// onkeypress repeats arrow keys in Mozilla/Opera
		}
		else
		{
			ref_suggest.input.keydown(ref_suggest.processKey);	// onkeydown repeats arrow keys in IE/Safari
		}

		// LIVE events
		$('form ul.reference_suggest li a').live('click', function(e) {
			ref_suggest.removeItem($(this).parent());
		});

		$('form ul.reference_suggest li').live('click', function(e) {
			ref_suggest.select($(this));
		});

		ref_suggest.input.closest('form')
			.unbind('submit.ref_suggest')
			.bind('submit.ref_suggest', function(event) {
				event.preventDefault();
	
				if (ref_suggest.input.val() != '')
				{
					ref_suggest.addValues(ref_suggest.input.val());
				}
				else
				{
					// join prototype similar to python
					ref_suggest.hidden.val('+'.join(ref_suggest.references).replace(/_/g,'.'));
	
					if (typeof(callbacks) === 'object') {
						$.each(callbacks, function(i, callback) {
							callback();
						});
					} else {
						this.submit();
					}
				}
			});

		ref_suggest.input.closest('ul').click(function() {
			ref_suggest.input.focus();
		});
	},

	updateInput: function() {
		var width = ((ref_suggest.input.val().length * 1) + 1);
		if (width > 15) { width = 15; }
		
		ref_suggest.input.css('width',  width+'em');
	},
	
	processKey: function(e) {

		ref_suggest.input.closest('ul').removeClass('error');
		
		ref_suggest.updateInput();

		if (ref_suggest.input.val() != "") {
			return;
		}

		var KEY = {
			LEFT: 37,
			UP: 38,
			RIGHT: 39,
			DOWN: 40,
			BACKSPACE: 8,
			DEL: 46,
			TAB: 9,
			RET: 13,
			ESC: 27,
			COMMA: 188,
			PAGEUP: 33,
			PAGEDOWN: 34
		};
			
		switch(e.keyCode) {
			case KEY.LEFT:
				ref_suggest.selectPrev();
				break;
			case KEY.RIGHT:
				ref_suggest.selectNext();
				break;
			case KEY.BACKSPACE:
				if (ref_suggest.selectedItem === false) {
					ref_suggest.selectPrev();
				} else {
					ref_suggest.removeSelected();
				}
				break;
			case KEY.DEL:
				ref_suggest.removeSelected();
				break;
			default:
//				ref_suggest.input.css('visibility', 'visible');
				if (ref_suggest.selectedItem !== false) {
					ref_suggest.selectedItem.removeClass('selected');
					ref_suggest.selectedItem = false;
				}
				return;
		}
		
		if (e.preventDefault) {
			e.preventDefault();
		}

		if (e.stopPropagation) {
			e.stopPropagation();
		}

		e.cancelBubble = true;
		e.returnValue = false;
	},

	deselect: function() {
		if (ref_suggest.selectedItem !== false)
		{
			ref_suggest.selectedItem.removeClass('selected');
			ref_suggest.selectedItem = false;
		}
	},

	select: function(li) {
		ref_suggest.deselect();
		
		ref_suggest.selectedItem = li;
		
		if (ref_suggest.selectedItem.length == 0 || ref_suggest.selectedItem.hasClass('input'))
		{
			ref_suggest.selectedItem = false;
		}
		else
		{
			ref_suggest.selectedItem.addClass('selected');
		}
	},
	
	selectPrev: function() {
		var e = ref_suggest.selectedItem || ref_suggest.input.parent();
		ref_suggest.select(e.prev('li'));
	},
	
	selectNext: function() {
		var e = ref_suggest.selectedItem || ref_suggest.input.parent();
		var li = e.next('li');
		if (li.length == 0)	//wrap around
		{
			li = e.siblings('li:first-child');
		}

		ref_suggest.select(li);
	},
	
	removeSelected: function() {
		if (ref_suggest.selectedItem === false) { return; }
		
		ref_suggest.removeItem(ref_suggest.selectedItem);
	},
	
	removeItem: function(li) {
		if (ref_suggest.selectedItem == li)
		{
			ref_suggest.selectedItem = false;
		}
		
		var ref = li.attr('rel');
		
		delete ref_suggest.references[ref];

		li.remove();
	},
	
	addValues: function(values) {
		var parts = values.split('+');

		for (var i = 0; i < parts.length; i++)
		{
			var str = $.trim(parts[i]);

			if (str == '') { continue; }
			str = str.uc_first();

			var ref = str.human_to_osis(reader.main.books.human_to_osis, '_', true);

			if (ref === false) {
				parts[i] = str.osis_to_human();

				if (parts[i] !== false)
				{
					ref = parts[i].human_to_osis(reader.main.books.human_to_osis, '_', true);
				}
			}

			if (ref !== false) {
				var osis = ref.split('_');
	
				if (osis.length < 3) {
					ref += '_1';
				}
			}

			if (ref === false || ref_suggest.references[ref]) { // Show error and then leave function
				ref_suggest.input.closest('ul').addClass('error');
				continue;
			}

			ref_suggest.input.closest('ul').removeClass('error');

			ref_suggest.references[ref] = ref;

			//get human
			var human = ref.osis_to_human();
			ref_suggest.input.parent().before('<li rel=\"'+ref+'\">'+human+'<a class=\"x\">x</a></li>');
		}
		ref_suggest.input.val('');
		ref_suggest.updateInput();
		ref_suggest.input.focus();
	},
	
	clear: function() {
		ref_suggest.input.closest('ul').find('li:not(li.input)').remove();
		ref_suggest.hidden.val('');
		ref_suggest.references = {};
	},
	
	removeValues: function(values) {
		var parts = values.split(',');

		for (var i = 0; i < parts.length; i++)
		{
			var str = $.trim(parts[i]);

			if (str == '') { continue; }
			str = str.uc_first();

			var ref = str.human_to_osis(reader.main.books.human_to_osis, '_', true);

			if (ref === false) {
				parts[i] = str.osis_to_human();

				if (parts[i] !== false)
				{
					ref = parts[i].human_to_osis(reader.main.books.human_to_osis, '_', true);
				}
			}

			if (ref !== false) {
				var osis = ref.split('_');
	
				if (osis.length < 3) {
					ref += '_1';
				}
			}

//			if (ref === false || ref_suggest.references[ref]) { // Show error and then leave function
//				ref_suggest.input.closest('ul').addClass('error');
//				continue;
//			}

			var item = ref_suggest.input.closest('ul').find('li[rel='+ref+']');
			if (item.length === 1)
			{
				ref_suggest.removeItem(item);
			}
		}
		ref_suggest.input.val('');
		ref_suggest.updateInput();
		ref_suggest.input.focus();
	}
};

// Google Analytics
// Load in dynamically

function loadGA() {
    var s1 = document.createElement('script');
    s1.setAttribute('id', 'googleanalytics');
    s1.setAttribute('src', 'http://www.google-analytics.com/urchin.js');
    s1.setAttribute('type', 'text/javascript');

    $(s1).bind('readystatechange', function () {
	    if ((s1.readyState == 'complete') || (s1.readyState == 'loaded')) {
			callGA();
	    }
	});

    $(s1).load(callGA);
    document.getElementsByTagName('head').item(0).appendChild(s1);
}

function callGA() {
    var s2 = document.createElement('script');
    s2.setAttribute('type', 'text/javascript');
    s2.text = '_uacct="UA-351257-4"; urchinTracker();';
    document.getElementsByTagName('body').item(0).appendChild(s2);

}

// Avatar Expand

var avatars = {
	init: function() {
		$('body').append('<div id="img_slide" style="padding: 5px; position: absolute; display: none;"><div id="img_bground" style="width: 100%; height: 100%"></div></div>');
		
		$('a.user-avatar.expand').bind('click', avatars.expand);
		
		$('#img_slide').click();
	},
	
	expand: function(event) {
		event.preventDefault();
		$(this).unbind('click', avatars.expand);
			
		var img_url = $(this).find('img').attr('src');
		img_url = img_url.replace(/\d+x\d+/, '512x512');
		
		var e = $('#img_slide');
		var i = $('#img_bground');
		
		i.css('background', '#EEE url('+img_url+')');
		i.hide();
		
		e.css('opacity', 0);
		e.show();
		
		var img = $(this).find('img');
		var offset = img.offset();
		
		e.css('height', '48px');
		e.css('width', '48px');
		
		e.css('top', offset.top - 6);
		e.css('left', offset.left - 6);
		
		//url(/img/loader_lg_black_on_lt_gray.gif) no-repeat center center
		e.css('background', '#EEE');
		e.css('border', '1px solid #CDCDCD');
		
		e.fadeTo(300, 1, function() {			
			e.animate({ width: "512px", height: "512px" }, 
				{ 
					duration: 150, 
					queue: false, 
					complete: function() {
						i.show();
						e.bind('click', avatars.contract);
					}
				}
			);
		});
	},
	
	contract: function(event) {
		var e = $(this);
		var i = $(this).find('#img_bground');
		
		e.unbind('click', avatars.contract);
		
		e.animate({ width: "48px", height: "48px" },
			{
				queue: false, 
				duration: 150, 
				complete: 
					function() { 
						i.hide(); 
						
						e.fadeTo(300, 0, function() {
							e.css('display', 'none');
						});
						
						$('a.user-avatar.expand').bind('click', avatars.expand);
					} 
			}
		);
	}
};

$(function() {
	avatars.init();

	// Focus username or password fields on sign-in page
	if ($('#password').val() === '') {
		$('#username').select();
	} else {
		$('#password').select();
	}

	// Country filtering
	$("select[name='country']").change(function() {  
		if ($(this).val() == 'US') { 
			$('div.state').css({display:'block'}); 
			$('div.province').css({display:'none'}); 
		} else { 
			$('div.state').css({display:'none'}); 
			$('div.province').css({display:'block'}); 
		} 
		
		var tz = $('#timezone').val();
		$.getJSON('/my/edit-profile/timezones/'+$(this).val(), function(data){ 
		
			var html_f = '<option value=""></option>'; 
			
			$.each(data, function(key, val) 
			{ 
				var selected = (tz == key) ? ' selected="selected"' : '';
				html_f += '<option value="'+key+'"'+selected+'>'+val[1]+'</option>'; 
			}); 
			
			$('#timezone').html(html_f); 
		}); 
	}); 
});
var config = {
	errors: {
		'unexpected': 'Unexpected error, try again later.'
	},
	site_domain_www: 'www.youversion.com',
	site_domain_readly: 'read.ly',
	site_domain: 'ext.youversion.com',
	site_protocol: 'http',
	username: 'youversion',
	password: 'youversiondev'
}
// Simple Set Clipboard System
// Author: Joseph Huckaby

var ZeroClipboard = {
	
	version: "1.0.4",
	clients: {}, // registered upload clients on page, indexed by id
	moviePath: 'ZeroClipboard.swf', // URL to movie
	nextId: 1, // ID of next movie
	
	$: function(thingy) {
		// simple DOM lookup utility function
		if (typeof(thingy) == 'string') thingy = document.getElementById(thingy);
		if (!thingy.addClass) {
			// extend element with a few useful methods
			thingy.hide = function() { this.style.display = 'none'; };
			thingy.show = function() { this.style.display = ''; };
			thingy.addClass = function(name) { this.removeClass(name); this.className += ' ' + name; };
			thingy.removeClass = function(name) {
				this.className = this.className.replace( new RegExp("\\s*" + name + "\\s*"), " ").replace(/^\s+/, '').replace(/\s+$/, '');
			};
			thingy.hasClass = function(name) {
				return !!this.className.match( new RegExp("\\s*" + name + "\\s*") );
			}
		}
		return thingy;
	},
	
	setMoviePath: function(path) {
		// set path to ZeroClipboard.swf
		this.moviePath = path;
	},
	
	dispatch: function(id, eventName, args) {
		// receive event from flash movie, send to client		
		var client = this.clients[id];
		if (client) {
			client.receiveEvent(eventName, args);
		}
	},
	
	register: function(id, client) {
		// register new client to receive events
		this.clients[id] = client;
	},
	
	getDOMObjectPosition: function(obj) {
		// get absolute coordinates for dom element
		var info = {
			left: 0, 
			top: 0, 
			width: obj.width ? obj.width : obj.offsetWidth, 
			height: obj.height ? obj.height : obj.offsetHeight
		};

		while (obj) {
			info.left += obj.offsetLeft;
			info.top += obj.offsetTop;
			obj = obj.offsetParent;
		}

		return info;
	},
	
	Client: function(elem) {
		// constructor for new simple upload client
		this.handlers = {};
		
		// unique ID
		this.id = ZeroClipboard.nextId++;
		this.movieId = 'ZeroClipboardMovie_' + this.id;
		
		// register client with singleton to receive flash events
		ZeroClipboard.register(this.id, this);
		
		// create movie
		if (elem) this.glue(elem);
	}
};

ZeroClipboard.Client.prototype = {
	
	id: 0, // unique ID for us
	ready: false, // whether movie is ready to receive events or not
	movie: null, // reference to movie object
	clipText: '', // text to copy to clipboard
	handCursorEnabled: true, // whether to show hand cursor, or default pointer cursor
	cssEffects: true, // enable CSS mouse effects on dom container
	handlers: null, // user event handlers
	
	glue: function(elem) {
		// glue to DOM element
		// elem can be ID or actual DOM element object
		this.domElement = ZeroClipboard.$(elem);
		
		// float just above object, or zIndex 99 if dom element isn't set
		var zIndex = 99;
		if (this.domElement.style.zIndex) {
			zIndex = parseInt(this.domElement.style.zIndex) + 1;
		}
		
		// find X/Y position of domElement
		var box = ZeroClipboard.getDOMObjectPosition(this.domElement);
		
		// create floating DIV above element
		this.div = document.createElement('div');
		var style = this.div.style;
		style.position = 'absolute';
		style.left = '' + box.left + 'px';
		style.top = '' + box.top + 'px';
		style.width = '' + box.width + 'px';
		style.height = '' + box.height + 'px';
		style.zIndex = zIndex;
		
		// style.backgroundColor = '#f00'; // debug
		
		var body = document.getElementsByTagName('body')[0];
		body.appendChild(this.div);
		
		this.div.innerHTML = this.getHTML( box.width, box.height );
	},
	
	getHTML: function(width, height) {
		// return HTML for movie
		var html = '';
		var flashvars = 'id=' + this.id + 
			'&width=' + width + 
			'&height=' + height;
			
		if (navigator.userAgent.match(/MSIE/)) {
			// IE gets an OBJECT tag
			var protocol = location.href.match(/^https/i) ? 'https://' : 'http://';
			html += '<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="'+protocol+'download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" width="'+width+'" height="'+height+'" id="'+this.movieId+'" align="middle"><param name="allowScriptAccess" value="always" /><param name="allowFullScreen" value="false" /><param name="movie" value="'+ZeroClipboard.moviePath+'" /><param name="loop" value="false" /><param name="menu" value="false" /><param name="quality" value="best" /><param name="bgcolor" value="#ffffff" /><param name="flashvars" value="'+flashvars+'"/><param name="wmode" value="transparent"/></object>';
		}
		else {
			// all other browsers get an EMBED tag
			html += '<embed id="'+this.movieId+'" src="'+ZeroClipboard.moviePath+'" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="'+width+'" height="'+height+'" name="'+this.movieId+'" align="middle" allowScriptAccess="always" allowFullScreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="'+flashvars+'" wmode="transparent" />';
		}
		return html;
	},
	
	hide: function() {
		// temporarily hide floater offscreen
		if (this.div) {
			this.div.style.left = '-2000px';
		}
	},
	
	show: function() {
		// show ourselves after a call to hide()
		this.reposition();
	},
	
	destroy: function() {
		// destroy control and floater
		if (this.domElement && this.div) {
			this.hide();
			this.div.innerHTML = '';
			
			var body = document.getElementsByTagName('body')[0];
			try { body.removeChild( this.div ); } catch(e) {;}
			
			this.domElement = null;
			this.div = null;
		}
	},
	
	reposition: function(elem) {
		// reposition our floating div, optionally to new container
		// warning: container CANNOT change size, only position
		if (elem) {
			this.domElement = ZeroClipboard.$(elem);
			if (!this.domElement) this.hide();
		}
		
		if (this.domElement && this.div) {
			var box = ZeroClipboard.getDOMObjectPosition(this.domElement);
			var style = this.div.style;
			style.left = '' + box.left + 'px';
			style.top = '' + box.top + 'px';
		}
	},
	
	setText: function(newText) {
		// set text to be copied to clipboard
		this.clipText = newText;
		if (this.ready) this.movie.setText(newText);
	},
	
	addEventListener: function(eventName, func) {
		// add user event listener for event
		// event types: load, queueStart, fileStart, fileComplete, queueComplete, progress, error, cancel
		eventName = eventName.toString().toLowerCase().replace(/^on/, '');
		if (!this.handlers[eventName]) this.handlers[eventName] = [];
		this.handlers[eventName].push(func);
	},
	
	setHandCursor: function(enabled) {
		// enable hand cursor (true), or default arrow cursor (false)
		this.handCursorEnabled = enabled;
		if (this.ready) this.movie.setHandCursor(enabled);
	},
	
	setCSSEffects: function(enabled) {
		// enable or disable CSS effects on DOM container
		this.cssEffects = !!enabled;
	},
	
	receiveEvent: function(eventName, args) {
		// receive event from flash
		eventName = eventName.toString().toLowerCase().replace(/^on/, '');
				
		// special behavior for certain events
		switch (eventName) {
			case 'load':
				// movie claims it is ready, but in IE this isn't always the case...
				// bug fix: Cannot extend EMBED DOM elements in Firefox, must use traditional function
				this.movie = document.getElementById(this.movieId);
				if (!this.movie) {
					var self = this;
					setTimeout( function() { self.receiveEvent('load', null); }, 1 );
					return;
				}
				
				// firefox on pc needs a "kick" in order to set these in certain cases
				if (!this.ready && navigator.userAgent.match(/Firefox/) && navigator.userAgent.match(/Windows/)) {
					var self = this;
					setTimeout( function() { self.receiveEvent('load', null); }, 100 );
					this.ready = true;
					return;
				}
				
				this.ready = true;
				this.movie.setText( this.clipText );
				this.movie.setHandCursor( this.handCursorEnabled );
				break;
			
			case 'mouseover':
				if (this.domElement && this.cssEffects) {
					this.domElement.addClass('hover');
					if (this.recoverActive) this.domElement.addClass('active');
				}
				break;
			
			case 'mouseout':
				if (this.domElement && this.cssEffects) {
					this.recoverActive = false;
					if (this.domElement.hasClass('active')) {
						this.domElement.removeClass('active');
						this.recoverActive = true;
					}
					this.domElement.removeClass('hover');
				}
				break;
			
			case 'mousedown':
				if (this.domElement && this.cssEffects) {
					this.domElement.addClass('active');
				}
				break;
			
			case 'mouseup':
				if (this.domElement && this.cssEffects) {
					this.domElement.removeClass('active');
					this.recoverActive = false;
				}
				break;
		} // switch eventName
		
		if (this.handlers[eventName]) {
			for (var idx = 0, len = this.handlers[eventName].length; idx < len; idx++) {
				var func = this.handlers[eventName][idx];
			
				if (typeof(func) == 'function') {
					// actual function reference
					func(this, args);
				}
				else if ((typeof(func) == 'object') && (func.length == 2)) {
					// PHP style object + method, i.e. [myObject, 'myMethod']
					func[0][ func[1] ](this, args);
				}
				else if (typeof(func) == 'string') {
					// name of function
					window[func](this, args);
				}
			} // foreach event handler defined
		} // user defined handler for event
	}
	
};

/**
 * @author alexander.farkas
 * 
 * @version 2.2
 */
(function($){
	
	$.manageAjax = (function(){
		var cache 			= {},
			queues			= {},
			presets 		= {},
			activeRequest 	= {},
			allRequests 	= {},
			defaults 		= {
						queue: true, //clear
						maxRequests: 1,
						abortOld: false,
						preventDoubbleRequests: true,
						cacheResponse: false,
						complete: function(){},
						error: function(ahr, status){
							var opts = this;
							if(status &&  status.indexOf('error') != -1){
								setTimeout(function(){
									var errStr = status +': ';
									if(ahr.status){
										errStr += 'status: '+ ahr.status +' | ';
									}
									errStr += 'URL: '+ opts.url;
									throw new Error(errStr);
								}, 1);
							}
						},
						success: function(){},
						abort: function(){}
				}
		;
		
		function create(name, settings){
			var publicMethods = {};
			presets[name] = presets[name] ||
				{};
			
			$.extend(true, presets[name], $.ajaxSettings, defaults, settings);
			if(!allRequests[name]){
				allRequests[name] 	= {};
				activeRequest[name] = {};
				activeRequest[name].queue = [];
				queues[name] 		= [];
			}
			$.each($.manageAjax, function(fnName, fn){
				if($.isFunction(fn) && fnName.indexOf('_') !== 0){
					publicMethods[fnName] = function(param){
						fn(name, param);
					};
				}
			});
			return publicMethods;
		}
		
		function complete(opts, args){
			
			if(args[1] == 'success'){
				opts.success.apply(opts, [args[0].successData, args[1]]);
				if (opts.global) {
					$.event.trigger("ajaxSuccess", args);
				}
			}
			
			if(args[1] === 'abort'){
				opts.abort.apply(opts, args);
				if(opts.global){
					$.active--;
					$.event.trigger("ajaxAbort", args);
				}
			}
			
			opts.complete.apply(opts, args);
			
			if (opts.global) {
				$.event.trigger("ajaxComplete", args);
			}
			
			if (opts.global && ! $.active){
				$.event.trigger("ajaxStop");
			}
			//args[0] = null; 
		}
		
		function proxy(oldFn, fn){
			return function(xhr, s, e){
				fn.call(this, xhr, s, e);
				oldFn.call(this, xhr, s, e);
				xhr = null;
				e = null;
			};
		}
		
					
		function callQueueFn(name){
			var q = queues[name];
			if(q && q.length){
				var fn = q.shift();
				if(fn){
					fn();
				}
			}
		}

		
		function add(name, opts){
			if(!presets[name]){
				create(name, opts);
			}
			opts = $.extend({}, presets[name], opts);
			//aliases
			var allR 	= allRequests[name],
				activeR = activeRequest[name],
				queue	= queues[name];
			
			var id 			= opts.type +'_'+ opts.url.replace(/\./g, '_'),
				oldComplete = opts.complete,
				ajaxFn 		= function(){
								activeR[id] = {
									xhr: $.ajax(opts),
									ajaxManagerOpts: opts
								};
								activeR.queue.push(id);
								return id;
							}
				;
				
			if(opts.data){
				id += (typeof opts.data == 'string') ? opts.data : $.param(opts.data);
			}
			
			if(opts.preventDoubbleRequests && allRequests[name][id]){
				return false;
			}
			
			allR[id] = true;
			
			opts.complete = function(xhr, s, e){
				if(opts.abortOld){
					$.each(activeR.queue, function(i, activeID){
						if(activeID == id){
							return false;
						}
						abort(name, activeID);
						return activeID;
					});
				}
				oldComplete.call(this, xhr, s, e);
				//stop memory leak
				if(activeRequest[name][id]){
					if(activeRequest[name][id] && activeRequest[name][id].xhr){
						activeRequest[name][id].xhr = null;
					} 
					activeRequest[name][id] = null;
				}
				xhr = null;
				activeRequest[name].queue = $.grep(activeRequest[name].queue, function(qid){
					return (qid !== id);
				});
				allR[id] = false;
				e = null;
				delete activeRequest[name][id];
			};
			
			if(cache[id]){
				ajaxFn = function(){
					activeR.queue.push(id);
					complete(opts, cache[id]);
					return id;
				};
			} else if(opts.cacheResponse){
				 opts.complete = proxy(opts.complete, function(xhr, s){
					if( s !== "success" && s !== "notmodified" ){
						return false;
					}
					cache[id][0].responseXML 	= xhr.responseXML;
					cache[id][0].responseText 	= xhr.responseText;
					cache[id][1] 				= s;
					//stop memory leak
					xhr = null;
					return id; //strict
				});
				
				opts.success = proxy(opts.success, function(data, s){
					cache[id] = [{
						successData: data,
						ajaxManagerOpts: opts
					}, s];
					data = null;
				});
			}
			
			ajaxFn.ajaxID = id;
			
			if(opts.queue){
				opts.complete = proxy(opts.complete, function(){
					
					callQueueFn(name);
				});
				 
				if(opts.queue === 'clear'){
					queue = clear(name);
				}
				
				queue.push(ajaxFn);
				
				if(activeR.queue.length < opts.maxRequests){
					callQueueFn(name); 
				}
				return id;
			}
			return ajaxFn();
		}
		
		function clear(name, shouldAbort){
			$.each(queues[name], function(i, fn){
				allRequests[name][fn.ajaxID] = false;
			});
			queues[name] = [];
			
			if(shouldAbort){
				abort(name);
			}
			return queues[name];
		}
		
		function getXHR(name, id){
			var ar = activeRequest[name];
			if(!ar || !allRequests[name][id]){
				return false;
			}
			if(ar[id]){
				return ar[id].xhr;
			}
			var queue = queues[name],
				xhrFn;
			$.each(queue, function(i, fn){
				if(fn.ajaxID == id){
					xhrFn = [fn, i];
					return false;
				}
				return xhrFn;
			});
			return xhrFn;
		}
		
		function abort(name, id){
			var ar = activeRequest[name];
			if(!ar){
				return false;
			}
			function abortID(qid){
				if(qid !== 'queue' && ar[qid] && typeof ar[qid].xhr !== 'unedfiend' && typeof ar[qid].xhr.abort !== 'unedfiend'){
					ar[qid].xhr.abort();
					complete(ar[qid].ajaxManagerOpts, [ar[qid].xhr, 'abort']);
				}
				return null;
			}
			if(id){
				return abortID(id);
			}
			return $.each(ar, abortID);
		}
		
		function unload(){
			$.each(presets, function(name){
				clear(name, true);
			});
			cache = {};
		}
		
		return {
			defaults: 		defaults,
			add: 			add,
			create: 		create,
			cache: 			cache,
			abort: 			abort,
			clear: 			clear,
			getXHR: 		getXHR,
			_activeRequest: activeRequest,
			_complete: 		complete,
			_allRequests: 	allRequests,
			_unload: 		unload
		};
	})();
	//stop memory leaks
	$(window).unload($.manageAjax._unload);
})(jQuery);
jQuery.fn.extend({everyTime:function(interval,label,fn,times,belay){return this.each(function(){jQuery.timer.add(this,interval,label,fn,times,belay);});},oneTime:function(interval,label,fn){return this.each(function(){jQuery.timer.add(this,interval,label,fn,1);});},stopTime:function(label,fn){return this.each(function(){jQuery.timer.remove(this,label,fn);});}});jQuery.extend({timer:{guid:1,global:{},regex:/^([0-9]+)\s*(.*s)?$/,powers:{'ms':1,'cs':10,'ds':100,'s':1000,'das':10000,'hs':100000,'ks':1000000},timeParse:function(value){if(value==undefined||value==null)
return null;var result=this.regex.exec(jQuery.trim(value.toString()));if(result[2]){var num=parseInt(result[1],10);var mult=this.powers[result[2]]||1;return num*mult;}else{return value;}},add:function(element,interval,label,fn,times,belay){var counter=0;if(jQuery.isFunction(label)){if(!times)
times=fn;fn=label;label=interval;}
interval=jQuery.timer.timeParse(interval);if(typeof interval!='number'||isNaN(interval)||interval<=0)
return;if(times&&times.constructor!=Number){belay=!!times;times=0;}
times=times||0;belay=belay||false;if(!element.$timers)
element.$timers={};if(!element.$timers[label])
element.$timers[label]={};fn.$timerID=fn.$timerID||this.guid++;var handler=function(){if(belay&&this.inProgress)
return;this.inProgress=true;if((++counter>times&&times!==0)||fn.call(element,counter)===false)
jQuery.timer.remove(element,label,fn);this.inProgress=false;};handler.$timerID=fn.$timerID;if(!element.$timers[label][fn.$timerID])
element.$timers[label][fn.$timerID]=window.setInterval(handler,interval);if(!this.global[label])
this.global[label]=[];this.global[label].push(element);},remove:function(element,label,fn){var timers=element.$timers,ret;if(timers){if(!label){for(label in timers)
this.remove(element,label,fn);}else if(timers[label]){if(fn){if(fn.$timerID){window.clearInterval(timers[label][fn.$timerID]);delete timers[label][fn.$timerID];}}else{for(var fn in timers[label]){window.clearInterval(timers[label][fn]);delete timers[label][fn];}}
for(ret in timers[label])break;if(!ret){ret=null;delete timers[label];}}
for(ret in timers)break;if(!ret)
element.$timers=null;}}}});if(jQuery.browser.msie)
jQuery(window).one("unload",function(){var global=jQuery.timer.global;for(var label in global){var els=global[label],i=els.length;while(--i)
jQuery.timer.remove(els[i],label);}});

jQuery.easing['jswing']=jQuery.easing['swing'];jQuery.extend(jQuery.easing,{def:'easeOutQuad',swing:function(x,t,b,c,d){return jQuery.easing[jQuery.easing.def](x,t,b,c,d);},easeInQuad:function(x,t,b,c,d){return c*(t/=d)*t+b;},easeOutQuad:function(x,t,b,c,d){return-c*(t/=d)*(t-2)+b;},easeInOutQuad:function(x,t,b,c,d){if((t/=d/2)<1)return c/2*t*t+b;return-c/2*((--t)*(t-2)-1)+b;},easeInCubic:function(x,t,b,c,d){return c*(t/=d)*t*t+b;},easeOutCubic:function(x,t,b,c,d){return c*((t=t/d-1)*t*t+1)+b;},easeInOutCubic:function(x,t,b,c,d){if((t/=d/2)<1)return c/2*t*t*t+b;return c/2*((t-=2)*t*t+2)+b;},easeInQuart:function(x,t,b,c,d){return c*(t/=d)*t*t*t+b;},easeOutQuart:function(x,t,b,c,d){return-c*((t=t/d-1)*t*t*t-1)+b;},easeInOutQuart:function(x,t,b,c,d){if((t/=d/2)<1)return c/2*t*t*t*t+b;return-c/2*((t-=2)*t*t*t-2)+b;},easeInQuint:function(x,t,b,c,d){return c*(t/=d)*t*t*t*t+b;},easeOutQuint:function(x,t,b,c,d){return c*((t=t/d-1)*t*t*t*t+1)+b;},easeInOutQuint:function(x,t,b,c,d){if((t/=d/2)<1)return c/2*t*t*t*t*t+b;return c/2*((t-=2)*t*t*t*t+2)+b;},easeInSine:function(x,t,b,c,d){return-c*Math.cos(t/d*(Math.PI/2))+c+b;},easeOutSine:function(x,t,b,c,d){return c*Math.sin(t/d*(Math.PI/2))+b;},easeInOutSine:function(x,t,b,c,d){return-c/2*(Math.cos(Math.PI*t/d)-1)+b;},easeInExpo:function(x,t,b,c,d){return(t==0)?b:c*Math.pow(2,10*(t/d-1))+b;},easeOutExpo:function(x,t,b,c,d){return(t==d)?b+c:c*(-Math.pow(2,-10*t/d)+1)+b;},easeInOutExpo:function(x,t,b,c,d){if(t==0)return b;if(t==d)return b+c;if((t/=d/2)<1)return c/2*Math.pow(2,10*(t-1))+b;return c/2*(-Math.pow(2,-10*--t)+2)+b;},easeInCirc:function(x,t,b,c,d){return-c*(Math.sqrt(1-(t/=d)*t)-1)+b;},easeOutCirc:function(x,t,b,c,d){return c*Math.sqrt(1-(t=t/d-1)*t)+b;},easeInOutCirc:function(x,t,b,c,d){if((t/=d/2)<1)return-c/2*(Math.sqrt(1-t*t)-1)+b;return c/2*(Math.sqrt(1-(t-=2)*t)+1)+b;},easeInElastic:function(x,t,b,c,d){var s=1.70158;var p=0;var a=c;if(t==0)return b;if((t/=d)==1)return b+c;if(!p)p=d*.3;if(a<Math.abs(c)){a=c;var s=p/4;}
else var s=p/(2*Math.PI)*Math.asin(c/a);return-(a*Math.pow(2,10*(t-=1))*Math.sin((t*d-s)*(2*Math.PI)/p))+b;},easeOutElastic:function(x,t,b,c,d){var s=1.70158;var p=0;var a=c;if(t==0)return b;if((t/=d)==1)return b+c;if(!p)p=d*.3;if(a<Math.abs(c)){a=c;var s=p/4;}
else var s=p/(2*Math.PI)*Math.asin(c/a);return a*Math.pow(2,-10*t)*Math.sin((t*d-s)*(2*Math.PI)/p)+c+b;},easeInOutElastic:function(x,t,b,c,d){var s=1.70158;var p=0;var a=c;if(t==0)return b;if((t/=d/2)==2)return b+c;if(!p)p=d*(.3*1.5);if(a<Math.abs(c)){a=c;var s=p/4;}
else var s=p/(2*Math.PI)*Math.asin(c/a);if(t<1)return-.5*(a*Math.pow(2,10*(t-=1))*Math.sin((t*d-s)*(2*Math.PI)/p))+b;return a*Math.pow(2,-10*(t-=1))*Math.sin((t*d-s)*(2*Math.PI)/p)*.5+c+b;},easeInBack:function(x,t,b,c,d,s){if(s==undefined)s=1.70158;return c*(t/=d)*t*((s+1)*t-s)+b;},easeOutBack:function(x,t,b,c,d,s){if(s==undefined)s=1.70158;return c*((t=t/d-1)*t*((s+1)*t+s)+1)+b;},easeInOutBack:function(x,t,b,c,d,s){if(s==undefined)s=1.70158;if((t/=d/2)<1)return c/2*(t*t*(((s*=(1.525))+1)*t-s))+b;return c/2*((t-=2)*t*(((s*=(1.525))+1)*t+s)+2)+b;},easeInBounce:function(x,t,b,c,d){return c-jQuery.easing.easeOutBounce(x,d-t,0,c,d)+b;},easeOutBounce:function(x,t,b,c,d){if((t/=d)<(1/2.75)){return c*(7.5625*t*t)+b;}else if(t<(2/2.75)){return c*(7.5625*(t-=(1.5/2.75))*t+.75)+b;}else if(t<(2.5/2.75)){return c*(7.5625*(t-=(2.25/2.75))*t+.9375)+b;}else{return c*(7.5625*(t-=(2.625/2.75))*t+.984375)+b;}},easeInOutBounce:function(x,t,b,c,d){if(t<d/2)return jQuery.easing.easeInBounce(x,t*2,0,c,d)*.5+b;return jQuery.easing.easeOutBounce(x,t*2-d,0,c,d)*.5+c*.5+b;}});


	/*
	 *	jquery.suggest 1.1 - 2007-08-06
	 *
	 *	Uses code and techniques from following libraries:
	 *	1. http://www.dyve.net/jquery/?autocomplete
	 *	2. http://dev.jquery.com/browser/trunk/plugins/interface/iautocompleter.js
	 *
	 *	All the new stuff written by Peter Vulgaris (www.vulgarisoip.com)
	 *	Feel free to do whatever you want with this file
	 *
	 */

	(function($) {

		$.suggest = function(input, options) {

			var $input = $(input).attr("autocomplete", "off");

			var timeout = false;		// hold timeout ID for suggestion results to appear
			var prevLength = 0;			// last recorded length of $input.val()
			var cache = [];				// cache MRU list
			var cacheSize = 0;			// size of cache in chars (bytes?)

			var $results = $('#'+options.resultsId);

			if ($results.length === 0) {
				$results = $(document.createElement("ul"));
				$results.attr('id', options.resultsId).addClass(options.resultsClass).appendTo('body');
			}

			resetPosition();
			$(window)
				.load(resetPosition)		// just in case user is changing size of page while loading
				.resize(resetPosition);

			$input.unbind('blur.reference_suggest');

			$input.bind('blur.reference_suggest', function() {
				setTimeout(function() { $results.hide() }, 200);
			});

			// help IE users if possible
			try {
				$results.bgiframe();
			} catch(e) { }

			// I really hate browser detection, but I don't see any other way
			if ($.browser.mozilla)
				$input.keypress(processKey);	// onkeypress repeats arrow keys in Mozilla/Opera
			else
				$input.keydown(processKey);		// onkeydown repeats arrow keys in IE/Safari

			function resetPosition() {
				// requires jquery.dimension plugin
				var offset = $input.offset();
				$results.css({
					top: (offset.top + input.offsetHeight - 2) + 'px',
					left: offset.left + 'px'
				});
			}

			function processKey(e) {

				var KEY = {
					LEFT: 37,
					UP: 38,
					RIGHT: 39,
					DOWN: 40,
					BACKSPACE: 8,
					DEL: 46,
					TAB: 9,
					RET: 13,
					ESC: 27,
					COMMA: 188,
					PAGEUP: 33,
					PAGEDOWN: 34
				};
				
				if (options.pane && reader[options.pane].reference_error === true)
				{
					$('#' + options.pane + ' input.reference').removeClass('error');
					reader[options.pane].reference_error = false;
				}

				// Handling up/down/escape/tab requires results to be visible
				// Handling enter requires that AND a result to be selected
				if ((/^(?:27|38|40|9)$/.test(e.keyCode) && $results.is(':visible')) || (/^(?:13)$/.test(e.keyCode) && getCurrentResult())) {

					if (e.preventDefault) {
						e.preventDefault();
					}

					if (e.stopPropagation) {
						e.stopPropagation();
					}

					e.cancelBubble = true;
					e.returnValue = false;

					switch(e.keyCode) {
						case KEY.UP: // Up
							prevResult();
							break;
						case KEY.DOWN: // Down
							nextResult();
							break;
						case KEY.TAB: // Tab
							nextResult();
							break;
						case KEY.RET: // return
							selectCurrentResult();
							break;
						case KEY.ESC: //	escape
							$results.hide();
							break;
					}
				} else if (/^(?:13)$/.test(e.keyCode)) {
					$results.hide();
				} else if ($input.val().length != prevLength) {
					if (timeout) {
						clearTimeout(timeout);
					}

					timeout = setTimeout(suggest, options.delay);
					prevLength = $input.val().length;
				}
			}

			function suggest() {
				resetPosition();
				
				var q = $.trim($input.val());

				if (q.length >= options.minchars) {

					q = q.toLowerCase();
					cached = checkCache(q);

					if (cached) {
						displayItems(cached['items']);
					} else {
						var txt = '';
						
						if (options.pane) {
							$.each(reader[options.pane].books.osis_to_human, function(i, val) {
								if (val[0].toLowerCase().indexOf(q) >= 0) {
									txt += val[0] + "\n";
								}
							});
						}
						
						var items = parseTxt(txt, q);
						displayItems(items);
						addToCache(q, items, txt.length);
					}
				} else {
					$results.hide();
				}
			}

			function checkCache(q) {

				for (var i = 0; i < cache.length; i++)
					if (cache[i]['q'] == q) {
						cache.unshift(cache.splice(i, 1)[0]);
						return cache[0];
					}

				return false;

			}

			function addToCache(q, items, size) {

				while (cache.length && (cacheSize + size > options.maxCacheSize)) {
					var cached = cache.pop();
					cacheSize -= cached['size'];
				}

				cache.push({
					q: q,
					size: size,
					items: items
					});

				cacheSize += size;

			}

			function displayItems(items) {

				if (!items)
					return;

				if (!items.length) {
					$results.hide();
					return;
				}

				var html = '';
				for (var i = 0; i < items.length; i++)
					html += '<li>' + items[i] + '</li>';

				$results.html(html).show();

				$results
					.children('li')
					.mouseover(function() {
						$results.children('li').removeClass(options.selectClass);
						$(this).addClass(options.selectClass);
					})
					.click(function(e) {
						e.preventDefault();
						e.stopPropagation();
						selectCurrentResult();
					});

			}

			function parseTxt(txt, q) {

				var items = [];
				var tokens = txt.split(options.delimiter);

				// parse returned data for non-empty items
				for (var i = 0; i < tokens.length; i++) {
					var token = $.trim(tokens[i]);
					if (token) {
						token = token.replace(
							new RegExp(q, 'ig'),
							function(q) { return '<span class="' + options.matchClass + '">' + q + '</span>' }
							);
						items[items.length] = token;
					}
				}

				return items;
			}

			function getCurrentResult() {

				if (!$results.is(':visible'))
					return false;

				var $currentResult = $results.children('li.' + options.selectClass);

				if (!$currentResult.length)
					$currentResult = false;

				return $currentResult;

			}

			function selectCurrentResult() {

				$currentResult = getCurrentResult();

				if ($currentResult) {
					$input.val($currentResult.text() + ' ');
					$results.hide();

					$input.focus();
					
					if (options.onSelect)
						options.onSelect.apply($input[0]);
					
				}

			}

			function nextResult() {

				$currentResult = getCurrentResult();

				if ($currentResult)
					$currentResult
						.removeClass(options.selectClass)
						.next()
							.addClass(options.selectClass);
				else
					$results.children('li:first-child').addClass(options.selectClass);

			}

			function prevResult() {

				$currentResult = getCurrentResult();

				if ($currentResult)
					$currentResult
						.removeClass(options.selectClass)
						.prev()
							.addClass(options.selectClass);
				else
					$results.children('li:last-child').addClass(options.selectClass);

			}

		}

		$.fn.reference_suggest = function(pane, options)
		{
			options = options || {};

			options.delay = options.delay || 100;
			options.resultsClass = options.resultsClass || 'ac_results';
			options.selectClass = options.selectClass || 'ac_over';
			options.matchClass = options.matchClass || 'ac_match';
			options.minchars = options.minchars || 2;
			options.delimiter = options.delimiter || '\n';
			options.onSelect = options.onSelect || false;
			options.maxCacheSize = options.maxCacheSize || 65536;
			options.pane = pane || false;
			options.resultsId = options.pane + '_' + options.resultsClass;

			if (options.pane !== 'main' || options.pane !== 'parallel') {
				options.pane = 'main';
			}

			this.each(function()
			{
				new $.suggest(this, options);
			});

			return this;
		};

	})(jQuery);


/*
 * jQuery Tooltip plugin 1.3
 *
 * http://bassistance.de/jquery-plugins/jquery-plugin-tooltip/
 * http://docs.jquery.com/Plugins/Tooltip
 *
 * Copyright (c) 2006 - 2008 Jörn Zaefferer
 *
 * $Id: jquery.tooltip.js 5741 2008-06-21 15:22:16Z joern.zaefferer $
 * 
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 */
 
;(function($) {
		// the tooltip element
	var helper = {},
		// default_settings
		default_settings = {},
		// the current tooltipped element
		current,
		// the title of the current element, used for restoring
		title,
		// timeout id for delayed tooltips
		tID,
		// IE 5.5 or 6
		IE = $.browser.msie && /MSIE\s(5\.5|6\.)/.test(navigator.userAgent),
		// flag for mouse tracking
		track = false;
	
	$.tooltip = {
		blocked: false,
		defaults: {
			delay: 200,
			fade: false,
			showURL: true,
			extraClass: "",
			top: 15,
			left: 15,
			id: "tooltip"
		},
		block: function() {
			$.tooltip.blocked = !$.tooltip.blocked;
		}
	};
	
	$.fn.extend({
		tooltip: function(settings) {
			default_settings = $.extend({}, $.tooltip.defaults, settings);
			createHelper(default_settings);

			// Below code uses event delegation so we don't have to bind
			// and unbind events each time we bring in more content
			this.live('mouseover', save).live('mouseout', hide).live('click', hide);
		},
		fixPNG: IE ? function() {
			return this.each(function () {
				var image = $(this).css('backgroundImage');
				if (image.match(/^url\(["']?(.*\.png)["']?\)$/i)) {
					image = RegExp.$1;
					$(this).css({
						'backgroundImage': 'none',
						'filter': "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=crop, src='" + image + "')"
					}).each(function () {
						var position = $(this).css('position');
						if (position != 'absolute' && position != 'relative')
							$(this).css('position', 'relative');
					});
				}
			});
		} : function() { return this; },
		unfixPNG: IE ? function() {
			return this.each(function () {
				$(this).css({'filter': '', backgroundImage: ''});
			});
		} : function() { return this; },
		hideWhenEmpty: function() {
			return this.each(function() {
				$(this)[ $(this).html() ? "show" : "hide" ]();
			});
		},
		url: function() {
			return this.attr('href') || this.attr('src');
		}
	});
	
	function createHelper(settings) {
		// there can be only one tooltip helper
		if( helper.parent )
			return;
		// create the helper, h3 for title, div for url
		helper.parent = $('<div id="' + settings.id + '"><h3></h3><div class="body"></div><div class="url"></div></div>')
			// add to document
			.appendTo(document.body)
			// hide it at first
			.hide();
			
		// apply bgiframe if available
		if ( $.fn.bgiframe )
			helper.parent.bgiframe();
		
		// save references to title and url elements
		helper.title = $('h3', helper.parent);
		helper.body = $('div.body', helper.parent);
		helper.url = $('div.url', helper.parent);
	}
	
	function settings(element) {
		return $.data(element, "tooltip");
	}
	
	// main event handler to start showing tooltips
	function handle(event) {
		// show helper, either with timeout or on instant
		if( settings(this).delay )
			tID = setTimeout(show, settings(this).delay);
		else
			show();
		
		// if selected, update the helper position when the mouse moves
		track = !!settings(this).track;
		$(document.body).bind('mousemove', update);
			
		// update at least once
		update(event);
	}
	
	// save elements title before the tooltip is displayed
	function save() {
		// Only needs to be ran the first time the element is hovered
		if (typeof(settings(this)) === 'undefined') {
			$.data(this, "tooltip", default_settings);
			this.tOpacity = helper.parent.css("opacity");
			// copy tooltip into its own expando and remove the title
			this.tooltipText = this.title;
			$(this).removeAttr("title");
			// also remove alt attribute to prevent default tooltip in IE
			this.alt = "";
		}
		
		// if this is the current source, or it has no title (occurs with click event), stop
		if ( $.tooltip.blocked || this == current || (!this.tooltipText && !settings(this).bodyHandler) )
			return;

		// save current
		current = this;
		title = this.tooltipText;
		
		if ( settings(this).bodyHandler ) {
			helper.title.hide();
			var bodyContent = settings(this).bodyHandler.call(this);
			if (bodyContent.nodeType || bodyContent.jquery) {
				helper.body.empty().append(bodyContent)
			} else {
				helper.body.html( bodyContent );
			}
			helper.body.show();
		} else if ( settings(this).showBody ) {
			var parts = title.split(settings(this).showBody);
			helper.title.html(parts.shift()).show();
			helper.body.empty();
			for(var i = 0, part; (part = parts[i]); i++) {
				if(i > 0)
					helper.body.append("<br/>");
				helper.body.append(part);
			}
			helper.body.hideWhenEmpty();
		} else {
			helper.title.html(title).show();
			helper.body.hide();
		}
		
		// if element has href or src, add and show it, otherwise hide it
		if( settings(this).showURL && $(this).url() )
			helper.url.html( $(this).url().replace('http://', '') ).show();
		else 
			helper.url.hide();
		
		// add an optional class for this tip
		helper.parent.addClass(settings(this).extraClass);

		// fix PNG background for IE
		if (settings(this).fixPNG )
			helper.parent.fixPNG();
			
		handle.apply(this, arguments);
	}
	
	// delete timeout and show helper
	function show() {
		tID = null;
		if ((!IE || !$.fn.bgiframe) && settings(current).fade) {
			if (helper.parent.is(":animated"))
				helper.parent.stop().show().fadeTo(settings(current).fade, current.tOpacity);
			else
				helper.parent.is(':visible') ? helper.parent.fadeTo(settings(current).fade, current.tOpacity) : helper.parent.fadeIn(settings(current).fade);
		} else {
			helper.parent.show();
		}
		update();
	}
	
	/**
	 * callback for mousemove
	 * updates the helper position
	 * removes itself when no current element
	 */
	function update(event)	{

		if ($.tooltip.blocked)
			return;
		
		if (event && event.target.tagName == "OPTION") {
			return;
		}
		
		// stop updating when tracking is disabled and the tooltip is visible
		if ( !track && helper.parent.is(":visible")) {
			$(document.body).unbind('mousemove', update)
		}
		
		// if no current element is available, remove this listener
		if( current == null ) {
			$(document.body).unbind('mousemove', update);
			return;	
		}
		
		// remove position helper classes
		helper.parent.removeClass("viewport-right").removeClass("viewport-bottom");
		
		var left = helper.parent[0].offsetLeft;
		var top = helper.parent[0].offsetTop;
		if (event) {
			// position the helper 15 pixel to bottom right, starting from mouse position
			left = event.pageX + settings(current).left;
			top = event.pageY + settings(current).top;
			var right='auto';
			if (settings(current).positionLeft) {
				right = $(window).width() - left;
				left = 'auto';
			}
			helper.parent.css({
				left: left,
				right: right,
				top: top
			});
		}
		
		var v = viewport(),
			h = helper.parent[0];
		// check horizontal position
		if (v.x + v.cx < h.offsetLeft + h.offsetWidth) {
			left -= h.offsetWidth + 20 + settings(current).left;
			helper.parent.css({left: left + 'px'}).addClass("viewport-right");
		}
		// check vertical position
		if (v.y + v.cy < h.offsetTop + h.offsetHeight) {
			top -= h.offsetHeight + 20 + settings(current).top;
			helper.parent.css({top: top + 'px'}).addClass("viewport-bottom");
		}
	}
	
	function viewport() {
		return {
			x: $(window).scrollLeft(),
			y: $(window).scrollTop(),
			cx: $(window).width(),
			cy: $(window).height()
		};
	}
	
	// hide helper and restore added classes and the title
	function hide(event) {
		if($.tooltip.blocked)
			return;
		// clear timeout if possible
		if(tID)
			clearTimeout(tID);
		// no more current element
		current = null;
		
		var tsettings = settings(this);
		function complete() {
			helper.parent.removeClass( tsettings.extraClass ).hide().css("opacity", "");
		}
		if ((!IE || !$.fn.bgiframe) && tsettings.fade) {
			if (helper.parent.is(':animated'))
				helper.parent.stop().fadeTo(tsettings.fade, 0, complete);
			else
				helper.parent.stop().fadeOut(tsettings.fade, complete);
		} else
			complete();
		
		if (settings(this).fixPNG) {
			helper.parent.unfixPNG();
		}
	}
})(jQuery);

/**
 * jquery.expose 0.14. Make HTML elements stand out.
 * 
 * http://flowplayer.org/tools/expose.html
 *
 * Copyright (c) 2008 Tero Piirainen (support@flowplayer.org)
 *
 * Released under the MIT License:
 * http://www.opensource.org/licenses/mit-license.php
 * 
 * >> Basically you can do anything you want but leave this header as is <<
 *
 * Since  : 0.10 - 10/06/2008
 * Version: 0.14 - Fri Nov 07 2008 16:51:35 GMT-0000 (GMT+00:00)
 */
(function($) { 
	
	function expose(el, params) { 
		
		var opts = {
			speed: 1000,
			zIndex: 1,
			opacity: 0.8,
			color:'#333',
			onClose: null
		};
		
		$.extend(opts, params);
		
		/* 
			create the fading "blanket" that sits on top of the document
			CSS settings for this are given in external stylesheet
		*/
		var blanket = $("#blanket");
		
		if (blanket.is(":visible")) {
			return;	
		}
		
		if (!blanket.length) {
			blanket = $('<div id="blanket"></div>').css({				
				position:'absolute', top:0, left:0,
				width:'100%',
				height:$(document).height(),
				display:'none'
			}).css("opacity", 0);
			
			$("body").append(blanket);	
		} 
		
		// these can vary from time to time
		blanket.css({
			backgroundColor:opts.color,
			zIndex:opts.zIndex	
		});
		
		// make given element sit on top of the blanket
		el.css({zIndex:opts.zIndex + 1});
		if (!/relative|absolute/i.test(el.css("position"))) {
			el.css("position", "relative");		
		}		 
		 
		// reveal blanket
		blanket.css("display", "block").fadeTo(opts.speed, opts.opacity);		
		

		function unexpose(fn) {			
			
			if (opts.onClose || fn) {
				if (!fn || fn.target) { fn = opts.onClose; }
				if (fn) { fn.call(el); }	
			}
			
			blanket.fadeTo(opts.speed, 0, function() {
				blanket.hide();
				el.css({zIndex:opts.zIndex -1});
			});				
			
			blanket.unbind("click.unexpose");
		}
		
		// esc button "unexposes"
		$(document).bind("keypress.unexpose", function(evt) {
			if (evt.keyCode == 27) {
				 unexpose();
				 $(document).unbind("keypress.unexpose");
			}
		});	
		
		blanket.bind("click.unexpose", unexpose);		
		$.unexpose = unexpose; 	
		
	}
	
	
	// jQuery plugin initialization
	$.fn.expose = function(params) {    
		expose(this, params);		
		return this; 
	}; 
	

})(jQuery);

/* jquery.swfobject.license.txt */
(function(A){A.flashPlayerVersion=function(){var D,B=null,I=false,H="ShockwaveFlash.ShockwaveFlash";if(!(D=navigator.plugins["Shockwave Flash"])){try{B=new ActiveXObject(H+".7")}catch(G){try{B=new ActiveXObject(H+".6");D=[6,0,21];B.AllowScriptAccess="always"}catch(F){if(D&&D[0]===6){I=true}}if(!I){try{B=new ActiveXObject(H)}catch(E){D="X 0,0,0"}}}if(!I&&B){try{D=B.GetVariable("$version")}catch(C){}}}else{D=D.description}D=D.match(/^[A-Za-z\s]*?(\d+)(\.|,)(\d+)(\s+r|,)(\d+)/);return[D[1]*1,D[3]*1,D[5]*1]}();A.flashExpressInstaller="expressInstall.swf";A.hasFlashPlayer=(A.flashPlayerVersion[0]!==0);A.hasFlashPlayerVersion=function(C){var B=A.flashPlayerVersion;C=(/string|integer/.test(typeof C))?C.toString().split("."):C;return(C)?(B[0]>=(C.major||C[0]||B[0])&&B[1]>=(C.minor||C[1]||B[1])&&B[2]>=(C.release||C[2]||B[2])):(B[0]!==0)};A.flash=function(M){if(!A.hasFlashPlayer){return false}var C=M.swf||"",K=M.params||{},E=document.createElement("body"),B,L,H,D,J,I,G,F;M.height=M.height||180;M.width=M.width||320;if(M.hasVersion&&!A.hasFlashPlayerVersion(M.hasVersion)){A.extend(M,{id:"SWFObjectExprInst",height:Math.max(M.height,137),width:Math.max(M.width,214)});C=M.expressInstaller||A.flashExpressInstaller;K={flashvars:{MMredirectURL:window.location.href,MMplayerType:(A.browser.msie&&A.browser.win)?"ActiveX":"PlugIn",MMdoctitle:document.title.slice(0,47)+" - Flash Player Installation"}}}if(M.flashvars&&typeof K==="object"){A.extend(K,{flashvars:M.flashvars})}for(J in (I=["swf","expressInstall","hasVersion","params","flashvars"])){delete M[I[J]]}B=[];for(J in M){if(typeof M[J]==="object"){L=[];for(I in M[J]){L.push(I.replace(/([A-Z])/,"-$1").toLowerCase()+":"+M[J][I]+";")}M[J]=L.join("")}B.push(J+'="'+M[J]+'"')}M=B.join(" ");if(typeof K==="object"){B=[];for(J in K){if(typeof K[J]==="object"){L=[];for(I in K[J]){if(typeof K[J][I]==="object"){H=[];for(G in K[J][I]){if(typeof K[J][I][G]==="object"){D=[];for(F in K[J][I][G]){D.push(F.replace(/([A-Z])/,"-$1").toLowerCase()+":"+K[J][I][G][F]+";")}K[J][I][G]=D.join("")}H.push(G+"{"+K[J][I][G]+"}")}K[J][I]=H.join("")}L.push(window.escape(I)+"="+window.escape(K[J][I]))}K[J]=L.join("&amp;")}B.push('<PARAM NAME="'+J+'" VALUE="'+K[J]+'">')}K=B.join("")}if(!(/style=/.test(M))){M+=' style="vertical-align:text-top;"'}if(!(/style=(.*?)vertical-align/.test(M))){M=M.replace(/style="/,'style="vertical-align:text-top;')}if(A.browser.msie){M+=' classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"';K='<PARAM NAME="movie" VALUE="'+C+'">'+K}else{M+=' type="application/x-shockwave-flash" data="'+C+'"'}E.innerHTML="<OBJECT "+M+">"+K+"</OBJECT>";return A(E.firstChild)};A.fn.flash=function(C){if(!A.hasFlashPlayer){return this}var B=0,D;while((D=this.eq(B++))[0]){D.html(A.flash(A.extend({},C)));if(D[0].firstChild.getAttribute("id")==="SWFObjectExprInst"){B=this.length}}return this}}(jQuery));
/*
(c) Copyrights 2007 - 2008

Original idea by by Binny V A, http://www.openjs.com/scripts/events/keyboard_shortcuts/
 
jQuery Plugin by Tzury Bar Yochay 
tzury.by@gmail.com
http://evalinux.wordpress.com
http://facebook.com/profile.php?id=513676303

Project's sites: 
http://code.google.com/p/js-hotkeys/
http://github.com/tzuryby/hotkeys/tree/master

License: same as jQuery license. 

USAGE:
    // simple usage
    $(document).bind('keydown', 'Ctrl+c', function(){ alert('copy anyone?');});
    
    // special options such as disableInIput
    $(document).bind('keydown', {combi:'Ctrl+x', disableInInput: true} , function() {});
    
Note:
    This plugin wraps the following jQuery methods: $.fn.find, $.fn.bind and $.fn.unbind
*/

(function (jQuery){
    // keep reference to the original $.fn.bind and $.fn.unbind
    jQuery.fn.__bind__ = jQuery.fn.bind;
    jQuery.fn.__unbind__ = jQuery.fn.unbind;
    jQuery.fn.__find__ = jQuery.fn.find;
    
    var hotkeys = {
        version: '0.7.8',
        override: /keydown|keypress|keyup/g,
        triggersMap: {},
        
        specialKeys: { 27: 'esc', 9: 'tab', 32:'space', 13: 'return', 8:'backspace', 145: 'scroll', 
            20: 'capslock', 144: 'numlock', 19:'pause', 45:'insert', 36:'home', 46:'del',
            35:'end', 33: 'pageup', 34:'pagedown', 37:'left', 38:'up', 39:'right',40:'down', 
            112:'f1',113:'f2', 114:'f3', 115:'f4', 116:'f5', 117:'f6', 118:'f7', 119:'f8', 
            120:'f9', 121:'f10', 122:'f11', 123:'f12', 191: '/'},
        
        shiftNums: { "`":"~", "1":"!", "2":"@", "3":"#", "4":"$", "5":"%", "6":"^", "7":"&", 
            "8":"*", "9":"(", "0":")", "-":"_", "=":"+", ";":":", "'":"\"", ",":"<", 
            ".":">",  "/":"?",  "\\":"|" },
        
        newTrigger: function (type, combi, callback) { 
            // i.e. {'keyup': {'ctrl': {cb: callback, disableInInput: false}}}
            var result = {};
            result[type] = {};
            result[type][combi] = {cb: callback, disableInInput: false};
            return result;
        }
    };
    // add firefox num pad char codes
    if (jQuery.browser.mozilla){
        hotkeys.specialKeys = jQuery.extend(hotkeys.specialKeys, { 96: '0', 97:'1', 98: '2', 99: 
            '3', 100: '4', 101: '5', 102: '6', 103: '7', 104: '8', 105: '9' });
    }
    
    // a wrapper around of $.fn.find 
    // see more at: http://groups.google.com/group/jquery-en/browse_thread/thread/18f9825e8d22f18d
    jQuery.fn.find = function( selector ) {
        this.query=selector;
        return jQuery.fn.__find__.apply(this, arguments);
	};
    
    jQuery.fn.unbind = function (type, combi, fn){
        if (jQuery.isFunction(combi)){
            fn = combi;
            combi = null;
        }
        if (combi && typeof combi === 'string'){
            var selectorId = ((this.prevObject && this.prevObject.query) || (this[0].id && this[0].id) || this[0]).toString();
            var hkTypes = type.split(' ');
            for (var x=0; x<hkTypes.length; x++){
                delete hotkeys.triggersMap[selectorId][hkTypes[x]][combi];
            }
        }
        // call jQuery original unbind
        return  this.__unbind__(type, fn);
    };
    
    jQuery.fn.bind = function(type, data, fn){
        // grab keyup,keydown,keypress
        var handle = type.match(hotkeys.override);
        
        if (jQuery.isFunction(data) || !handle){
            // call jQuery.bind only
            return this.__bind__(type, data, fn);
        }
        else{
            // split the job
            var result = null,            
            // pass the rest to the original $.fn.bind
            pass2jq = jQuery.trim(type.replace(hotkeys.override, ''));
            
            // see if there are other types, pass them to the original $.fn.bind
            if (pass2jq){
                result = this.__bind__(pass2jq, data, fn);
            }            
            
            if (typeof data === "string"){
                data = {'combi': data};
            }
            if(data.combi){
                for (var x=0; x < handle.length; x++){
                    var eventType = handle[x];
                    var combi = data.combi.toLowerCase(),
                        trigger = hotkeys.newTrigger(eventType, combi, fn),
                        selectorId = ((this.prevObject && this.prevObject.query) || (this[0].id && this[0].id) || this[0]).toString();
                        
                    //trigger[eventType][combi].propagate = data.propagate;
                    trigger[eventType][combi].disableInInput = data.disableInInput;
                    
                    // first time selector is bounded
                    if (!hotkeys.triggersMap[selectorId]) {
                        hotkeys.triggersMap[selectorId] = trigger;
                    }
                    // first time selector is bounded with this type
                    else if (!hotkeys.triggersMap[selectorId][eventType]) {
                        hotkeys.triggersMap[selectorId][eventType] = trigger[eventType];
                    }
                    // make trigger point as array so more than one handler can be bound
                    var mapPoint = hotkeys.triggersMap[selectorId][eventType][combi];
                    if (!mapPoint){
                        hotkeys.triggersMap[selectorId][eventType][combi] = [trigger[eventType][combi]];
                    }
                    else if (mapPoint.constructor !== Array){
                        hotkeys.triggersMap[selectorId][eventType][combi] = [mapPoint];
                    }
                    else {
                        hotkeys.triggersMap[selectorId][eventType][combi][mapPoint.length] = trigger[eventType][combi];
                    }
                    
                    // add attribute and call $.event.add per matched element
                    this.each(function(){
                        // jQuery wrapper for the current element
                        var jqElem = jQuery(this);
                        
                        // element already associated with another collection
                        if (jqElem.attr('hkId') && jqElem.attr('hkId') !== selectorId){
                            selectorId = jqElem.attr('hkId') + ";" + selectorId;
                        }
                        jqElem.attr('hkId', selectorId);
                    });
                    result = this.__bind__(handle.join(' '), data, hotkeys.handler)
                }
            }
            return result;
        }
    };
    // work-around for opera and safari where (sometimes) the target is the element which was last 
    // clicked with the mouse and not the document event it would make sense to get the document
    hotkeys.findElement = function (elem){
        if (!jQuery(elem).attr('hkId')){
            if (jQuery.browser.opera || jQuery.browser.safari){
                while (!jQuery(elem).attr('hkId') && elem.parentNode){
                    elem = elem.parentNode;
                }
            }
        }
        return elem;
    };
    // the event handler
    hotkeys.handler = function(event) {
        var target = hotkeys.findElement(event.currentTarget), 
            jTarget = jQuery(target),
            ids = jTarget.attr('hkId');
        
        if(ids){
            ids = ids.split(';');
            var code = event.which,
                type = event.type,
                special = hotkeys.specialKeys[code],
                // prevent f5 overlapping with 't' (or f4 with 's', etc.)
                character = !special && String.fromCharCode(code).toLowerCase(),
                shift = event.shiftKey,
                ctrl = event.ctrlKey,            
                // patch for jquery 1.2.5 && 1.2.6 see more at:  
                // http://groups.google.com/group/jquery-en/browse_thread/thread/83e10b3bb1f1c32b
                alt = event.altKey || event.originalEvent.altKey,
                mapPoint = null;

            for (var x=0; x < ids.length; x++){
                if (hotkeys.triggersMap[ids[x]][type]){
                    mapPoint = hotkeys.triggersMap[ids[x]][type];
                    break;
                }
            }
            
            //find by: id.type.combi.options            
            if (mapPoint){ 
                var trigger;
                // event type is associated with the hkId
                if(!shift && !ctrl && !alt) { // No Modifiers
                    trigger = mapPoint[special] ||  (character && mapPoint[character]);
                }
                else{
                    // check combinations (alt|ctrl|shift+anything)
                    var modif = '';
                    if(alt) modif +='alt+';
                    if(ctrl) modif+= 'ctrl+';
                    if(shift) modif += 'shift+';
                    
                    // modifiers + special keys or modifiers + character or modifiers + shift character or just shift character
                    trigger = mapPoint[modif+special];
                    if (!trigger){
                        if (character){
                            trigger = mapPoint[modif+character] 
                                || mapPoint[modif+hotkeys.shiftNums[character]]
                                // '$' can be triggered as 'Shift+4' or 'Shift+$' or just '$'
                                || (modif === 'shift+' && mapPoint[hotkeys.shiftNums[character]]);
                        }
                    }
                }
                if (trigger){
                    var result = false;
                    for (var x=0; x < trigger.length; x++){
                        if(trigger[x].disableInInput){
                            // double check event.currentTarget and event.target
                            var elem = jQuery(event.target);
                            if (jTarget.is("input") || jTarget.is("textarea") 
                                || elem.is("input") || elem.is("textarea")) {
                                return true;
                            }
                        }
                        // call the registered callback function
                        result = result || trigger[x].cb.apply(this, [event]);
                    }
                    return result;
                }
            }
        }
    };
    // place it under window so it can be extended and overridden by others
    window.hotkeys = hotkeys;
    return jQuery;
})(jQuery);

var tb_pathToImage=config.site_protocol+'://'+config.site_domain+"/img/loadingAnimation.gif";$(document).ready(function(){tb_init('a.thickbox, area.thickbox, input.thickbox');imgLoader=new Image();imgLoader.src=tb_pathToImage;});function tb_init(domChunk){$(domChunk).click(function(){var t=this.title||this.name||null;var a=this.href||this.alt;var g=this.rel||false;tb_show(t,a,g);this.blur();return false;});}
function tb_show(caption,url,imageGroup){try{if(typeof document.body.style.maxHeight==="undefined"){$("body","html").css({height:"100%",width:"100%"});$("html").css("overflow","hidden");if(document.getElementById("TB_HideSelect")===null){$("body").append("<iframe id='TB_HideSelect'></iframe><div id='TB_overlay'></div><div id='TB_window'></div>");$("#TB_overlay").click(tb_remove);}}else{if(document.getElementById("TB_overlay")===null){$("body").append("<div id='TB_overlay'></div><div id='TB_window'></div>");$("#TB_overlay").click(tb_remove);}}
if(tb_detectMacXFF()){$("#TB_overlay").addClass("TB_overlayMacFFBGHack");}else{$("#TB_overlay").addClass("TB_overlayBG");}
if(caption===null){caption="";}
$("body").append("<div id='TB_load'><img src='"+imgLoader.src+"' /></div>");$('#TB_load').show();var baseURL;if(url.indexOf("?")!==-1){baseURL=url.substr(0,url.indexOf("?"));}else{baseURL=url;}
var urlString=/\.jpg$|\.jpeg$|\.png$|\.gif$|\.bmp$/;var urlType=baseURL.toLowerCase().match(urlString);if(urlType=='.jpg'||urlType=='.jpeg'||urlType=='.png'||urlType=='.gif'||urlType=='.bmp'){TB_PrevCaption="";TB_PrevURL="";TB_PrevHTML="";TB_NextCaption="";TB_NextURL="";TB_NextHTML="";TB_imageCount="";TB_FoundURL=false;if(imageGroup){TB_TempArray=$("a[@rel="+imageGroup+"]").get();for(TB_Counter=0;((TB_Counter<TB_TempArray.length)&&(TB_NextHTML===""));TB_Counter++){var urlTypeTemp=TB_TempArray[TB_Counter].href.toLowerCase().match(urlString);if(!(TB_TempArray[TB_Counter].href==url)){if(TB_FoundURL){TB_NextCaption=TB_TempArray[TB_Counter].title;TB_NextURL=TB_TempArray[TB_Counter].href;TB_NextHTML="<span id='TB_next'>&nbsp;&nbsp;<a href='#'>Next &gt;</a></span>";}else{TB_PrevCaption=TB_TempArray[TB_Counter].title;TB_PrevURL=TB_TempArray[TB_Counter].href;TB_PrevHTML="<span id='TB_prev'>&nbsp;&nbsp;<a href='#'>&lt; Prev</a></span>";}}else{TB_FoundURL=true;TB_imageCount="Image "+(TB_Counter+1)+" of "+(TB_TempArray.length);}}}
imgPreloader=new Image();imgPreloader.onload=function(){imgPreloader.onload=null;var pagesize=tb_getPageSize();var x=pagesize[0]-150;var y=pagesize[1]-150;var imageWidth=imgPreloader.width;var imageHeight=imgPreloader.height;if(imageWidth>x){imageHeight=imageHeight*(x/imageWidth);imageWidth=x;if(imageHeight>y){imageWidth=imageWidth*(y/imageHeight);imageHeight=y;}}else if(imageHeight>y){imageWidth=imageWidth*(y/imageHeight);imageHeight=y;if(imageWidth>x){imageHeight=imageHeight*(x/imageWidth);imageWidth=x;}}
TB_WIDTH=imageWidth+30;TB_HEIGHT=imageHeight+60;$("#TB_window").append("<a href='' id='TB_ImageOff' title='Close'><img id='TB_Image' src='"+url+"' width='"+imageWidth+"' height='"+imageHeight+"' alt='"+caption+"'/></a>"+"<div id='TB_caption'>"+caption+"<div id='TB_secondLine'>"+TB_imageCount+TB_PrevHTML+TB_NextHTML+"</div></div><div id='TB_closeWindow'><a href='#' id='TB_closeWindowButton' title='Close'>close</a></div>");$("#TB_closeWindowButton").click(tb_remove);if(!(TB_PrevHTML==="")){function goPrev(){if($(document).unbind("click",goPrev)){$(document).unbind("click",goPrev);}
$("#TB_window").remove();$("body").append("<div id='TB_window'></div>");tb_show(TB_PrevCaption,TB_PrevURL,imageGroup);return false;}
$("#TB_prev").click(goPrev);}
if(!(TB_NextHTML==="")){function goNext(){$("#TB_window").remove();$("body").append("<div id='TB_window'></div>");tb_show(TB_NextCaption,TB_NextURL,imageGroup);return false;}
$("#TB_next").click(goNext);}
document.onkeydown=function(e){if(e==null){keycode=event.keyCode;}else{keycode=e.which;}
if(keycode==27){tb_remove();}else if(keycode==190){if(!(TB_NextHTML=="")){document.onkeydown="";goNext();}}else if(keycode==188){if(!(TB_PrevHTML=="")){document.onkeydown="";goPrev();}}};tb_position();$("#TB_load").remove();$("#TB_ImageOff").click(tb_remove);$("#TB_window").css({display:"block"});};imgPreloader.src=url;}else{var queryString=url.replace(/^[^\?]+\??/,'');var params=tb_parseQuery(queryString);TB_WIDTH=(params['width']*1)+30||630;TB_HEIGHT=(params['height']*1)+40||440;ajaxContentW=TB_WIDTH-30;ajaxContentH=TB_HEIGHT-45;if(url.indexOf('TB_iframe')!=-1){urlNoQuery=url.split('TB_');$("#TB_iframeContent").remove();if(params['modal']!="true"){$("#TB_window").append("<div id='TB_title'><div id='TB_ajaxWindowTitle'>"+caption+"</div><div id='TB_closeAjaxWindow'><a href='#' id='TB_closeWindowButton' title='Close'>close</a></div></div><iframe frameborder='0' hspace='0' src='"+urlNoQuery[0]+"' id='TB_iframeContent' name='TB_iframeContent"+Math.round(Math.random()*1000)+"' onload='tb_showIframe()' style='width:"+(ajaxContentW+29)+"px;height:"+(ajaxContentH+17)+"px;' > </iframe>");}else{$("#TB_overlay").unbind();$("#TB_window").append("<iframe frameborder='0' hspace='0' src='"+urlNoQuery[0]+"' id='TB_iframeContent' name='TB_iframeContent"+Math.round(Math.random()*1000)+"' onload='tb_showIframe()' style='width:"+(ajaxContentW+29)+"px;height:"+(ajaxContentH+17)+"px;'> </iframe>");}}else{if($("#TB_window").css("display")!="block"){if(params['modal']!="true"){$("#TB_window").append("<div id='TB_title'><div id='TB_ajaxWindowTitle'>"+caption+"</div><div id='TB_closeAjaxWindow'><a href='#' id='TB_closeWindowButton'>close</a></div></div><div id='TB_ajaxContent' style='width:"+ajaxContentW+"px;height:"+ajaxContentH+"px'></div>");}else{$("#TB_overlay").unbind();$("#TB_window").append("<div id='TB_ajaxContent' class='TB_modal' style='width:"+ajaxContentW+"px;height:"+ajaxContentH+"px;'></div>");}}else{$("#TB_ajaxContent")[0].style.width=ajaxContentW+"px";$("#TB_ajaxContent")[0].style.height=ajaxContentH+"px";$("#TB_ajaxContent")[0].scrollTop=0;$("#TB_ajaxWindowTitle").html(caption);}}
$("#TB_closeWindowButton").click(tb_remove);if(url.indexOf('TB_inline')!=-1){$("#TB_ajaxContent").append($('#'+params['inlineId']).children());$("#TB_window").unload(function(){$('#'+params['inlineId']).append($("#TB_ajaxContent").children());});tb_position();$("#TB_load").remove();$("#TB_window").css({display:"block"});}else if(url.indexOf('TB_iframe')!=-1){tb_position();if($.browser.safari){$("#TB_load").remove();$("#TB_window").css({display:"block"});}}else{$("#TB_ajaxContent").load(url+="&random="+(new Date().getTime()),function(){tb_position();$("#TB_load").remove();tb_init("#TB_ajaxContent a.thickbox");$("#TB_window").css({display:"block"});});}}
if(!params['modal']){document.onkeyup=function(e){if(e==null){keycode=event.keyCode;}else{keycode=e.which;}
if(keycode==27){tb_remove();}};}}catch(e){}}
function tb_showIframe(){$("#TB_load").remove();$("#TB_window").css({display:"block"});}
function tb_remove(){$("#TB_imageOff").unbind("click");$("#TB_closeWindowButton").unbind("click");$("#TB_window").fadeOut("fast",function(){$('#TB_window,#TB_overlay,#TB_HideSelect').trigger("unload").unbind().remove();});$("#TB_load").remove();if(typeof document.body.style.maxHeight=="undefined"){$("body","html").css({height:"auto",width:"auto"});$("html").css("overflow","");}
document.onkeydown="";document.onkeyup="";return false;}
function tb_position(){$("#TB_window").css({marginLeft:'-'+parseInt((TB_WIDTH/2),10)+'px',width:TB_WIDTH+'px'});if(!(jQuery.browser.msie&&jQuery.browser.version<7)){$("#TB_window").css({marginTop:'-'+parseInt((TB_HEIGHT/2),10)+'px'});}}
function tb_parseQuery(query){var Params={};if(!query){return Params;}
var Pairs=query.split(/[;&]/);for(var i=0;i<Pairs.length;i++){var KeyVal=Pairs[i].split('=');if(!KeyVal||KeyVal.length!=2){continue;}
var key=unescape(KeyVal[0]);var val=unescape(KeyVal[1]);val=val.replace(/\+/g,' ');Params[key]=val;}
return Params;}
function tb_getPageSize(){var de=document.documentElement;var w=window.innerWidth||self.innerWidth||(de&&de.clientWidth)||document.body.clientWidth;var h=window.innerHeight||self.innerHeight||(de&&de.clientHeight)||document.body.clientHeight;arrayPageSize=[w,h];return arrayPageSize;}
function tb_detectMacXFF(){var userAgent=navigator.userAgent.toLowerCase();if(userAgent.indexOf('mac')!=-1&&userAgent.indexOf('firefox')!=-1){return true;}}
(function($){function toIntegersAtLease(n)
{return n<10?'0'+n:n;}
Date.prototype.toJSON=function(date)
{return this.getUTCFullYear()+'-'+
toIntegersAtLease(this.getUTCMonth())+'-'+
toIntegersAtLease(this.getUTCDate());};var escapeable=/["\\\x00-\x1f\x7f-\x9f]/g;var meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'};$.quoteString=function(string)
{if(escapeable.test(string))
{return'"'+string.replace(escapeable,function(a)
{var c=meta[a];if(typeof c==='string'){return c;}
c=a.charCodeAt();return'\\u00'+Math.floor(c/16).toString(16)+(c%16).toString(16);})+'"';}
return'"'+string+'"';};$.toJSON=function(o,compact)
{var type=typeof(o);if(type=="undefined")
return"undefined";else if(type=="number"||type=="boolean")
return o+"";else if(o===null)
return"null";if(type=="string")
{return $.quoteString(o);}
if(type=="object"&&typeof o.toJSON=="function")
return o.toJSON(compact);if(type!="function"&&typeof(o.length)=="number")
{var ret=[];for(var i=0;i<o.length;i++){ret.push($.toJSON(o[i],compact));}
if(compact)
return"["+ret.join(",")+"]";else
return"["+ret.join(", ")+"]";}
if(type=="function"){throw new TypeError("Unable to convert object of type 'function' to json.");}
var ret=[];for(var k in o){var name;type=typeof(k);if(type=="number")
name='"'+k+'"';else if(type=="string")
name=$.quoteString(k);else
continue;var val=$.toJSON(o[k],compact);if(typeof(val)!="string"){continue;}
if(compact)
ret.push(name+":"+val);else
ret.push(name+": "+val);}
return"{"+ret.join(", ")+"}";};$.compactJSON=function(o)
{return $.toJSON(o,true);};$.evalJSON=function(src)
{return eval("("+src+")");};$.secureEvalJSON=function(src)
{var filtered=src;filtered=filtered.replace(/\\["\\\/bfnrtu]/g,'@');filtered=filtered.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']');filtered=filtered.replace(/(?:^|:|,)(?:\s*\[)+/g,'');if(/^[\],:{}\s]*$/.test(filtered))
return eval("("+src+")");else
throw new SyntaxError("Error parsing JSON, source is not valid.");};})(jQuery);
	String.prototype.is_osis = function() {
		var regexp = /^[a-zA-Z0-9]+(?:.[0-9]+){1,2}$/;
		reference = this.match(regexp);

		if (reference !== null && reference.length > 0) {
			return true;
		}

		return false;
	}

	String.prototype.url_to_human = function() {
		var url = '';
		if (this.search(/.+bible\/[a-zA-Z0-9]+\/[a-zA-Z0-9]+\//) !== -1) {
			url = this.replace(/.+bible\/[a-zA-Z]+\//, '');
		} else {
			url = this.replace(/.+bible\//, '');
		}

		var reference = url.replace(/\//g, '.').uc_first();
		reference = reference.replace(/-[0-9]+$/, '');

		return reference;
	}

	String.prototype.osis_to_url = function() {
		var osis = this.split(/[\._]/);

		if (typeof(osis[2]) === 'undefined') {
			osis = osis[0] + '/' + osis[1];
		} else {
			osis = osis[0] + '/' + osis[1] + '/' + osis[2];
		}

		return osis.toLowerCase();
	}

	String.prototype.osis_to_short_url = function(version) {
		var osis = this.split(/[\._]/);

		if (typeof(osis[2]) === 'undefined') {
			osis = osis[0]+osis[1];
		} else {
			osis = osis[0]+osis[1]+'.'+osis[2];
		}

		if (typeof(version) != 'undefined') {
			osis += '.'+version.toUpperCase();
		}
		
		return osis;
	}
	
	String.prototype.osis_to_css_style = function() {
		return this.replace(/\./g, '_').replace(/-.+/g, '');
	}

	String.prototype.css_style_to_osis = function() {
		return this.replace(/_/g, '.');
	}

	String.prototype.opposite_pane = function() {
		return (this.toString() === 'main') ? 'parallel' : 'main';
	}

	String.prototype.osis_list_from_range = function() {
		var reference = this.toString();
		var osis_list = [];

		if (this.search('-') > -1) {
			var reference_parts = reference.split(/-/);
	
			var separator = '.';
			if (this.search('_') > -1) {
				separator = '_';
			}
	
			var osis = reference_parts[0].split(separator);
	
			var ref_length = reference_parts[0].length;
			var start = Number(osis[2]);
			var end   = Number(reference_parts[1]);

			if (start > end) {
				var end = start;
			}

			for (i = start; i <= end; i++)
			{
				osis_list.push(osis[0]+separator+osis[1]+separator+i);
			}
		} else {
			osis_list.push(reference);
		}

		return osis_list;
	}

	// User

	var user = {

		user_id: false,
		username: false,

		init: function() {

			reader.selected_plus_string = '';

			user.load_settings();

			// Intercept form submit on login modal
			$('#modal-login form').submit(function(event) {
				event.preventDefault();
				var that = this;
				$(that).find('.buttons').hide();
				$(that).find('.loading').show();
		
				$.ajax({
					cache: false,
					data: $(this).serialize(),
					dataType: 'json',
					success: function(j) {
						if (j.code === 200) {
							user.setup(j.data);
							user.sign_in_close();
						} else {
							var html_f = '';
							$.each(j.data.errors, function(i, val) {
								html_f += '<li>'+val+'</li>';
							});
							$(that).find('ul.errors').html(html_f).show();
							$('#password').select();
						}
						$(that).find('.buttons').show();
						$(that).find('.loading').hide();
					},
					type: 'POST',
					url: '/bible/sign_in'
				});
			});
		},

		// Setup user and change any page elements necessary
		setup: function(u) {
			SIGNED_IN = true;

			user.user_id = u.user_id;
			user.username = u.username;

			// Swap out user-nav
			var user_nav = $('#user-nav');
			user_nav.fadeOut(
				250,
				function() {
					user_nav.load(
						'/bible/header #user-nav > ul',
						function() {
							user_nav.fadeIn(250);
						}
					);
				}
			);

			// Turn on any edit button on contrib modal if needed
			var contrib_id = $('#contrib').attr('class').replace(/contrib| /gi, '');
			if (contrib_id !== '') {
				// TODO: Fix to work with restructure
				//meta.contribution_modal_load(contrib_id, true);
			}

			// Load user data (contributions/journals) now that they are logged in
			meta.contributions_community_load(reader.selected_plus_string);
			meta.contributions_my_load(reader.selected_plus_string);
			meta.journals_load(reader.selected_plus_string);

			// Re-setup any meta actions
			meta.action_function();
		},

		// Show login modal
		sign_in: function() {
			$('#modal-login form')
				.removeClass('loading')
				.find('ul.errors').hide()
				.end().get(0).reset();
			tb_show('Sign In', '#TB_inline?height=345&width=300&inlineId=modal-login', false);

			$('#TB_ajaxContent').css({'height': 'auto'});

			$('#username').focus();
		},

		// Close login modal
		sign_in_close: function() {
			tb_remove();
		},

		load_settings: function() {
			var settings = $.cookie('settings');

			if (settings !== null) {
				settings = $.secureEvalJSON(settings);
			}

			if (settings !== null && settings.meta !== null && settings.meta.widgets !== null) {
				meta.widgets    = settings.meta.widgets;
			}
		},

		// Save settings to DB and cookie
		save_settings: function() {
			// TODO: Save to DB, for now just cookie, will be more important
			// to save to DB once we update iPhone/BB/etc
			var settings = {
				reader: {
					main: {
						reference: reader.osis('main', '.'),
						version: reader.main.version
					},
					parallel: {
						reference: reader.osis('parallel', '.'),
						version: reader.parallel.version
					}
				},
				meta: {
					widgets: meta.widgets
				}
			};

			settings = $.toJSON(settings);

			$.cookie('settings', settings, {expires: 30, path: '/'});
		}
	};

	// Reader

	var reader = {
		main: {
			version: 'asv',
			first_book: 'Gen',
			book: '',
			chapter: '',
			verse: '',
			previous: '',
			before: '',
			after: '',
			next: '',
			loaded: [],
			pos_y: {
				current: '',
				previous: ''
			},
			reference_error: false,
			scroll_to: false,
			loading_in_height: 0
		},
		parallel: {
			version: 'kjv',
			first_book: 'Gen',
			book: 'Gen',
			chapter: '1',
			verse: '1',
			previous: '',
			before: '',
			after: '',
			next: '',
			loaded: [],
			pos_y: {
				current: '',
				previous: ''
			},
			enabled: false,
			sync: true,
			reference_error: false,
			loading_in_height: 0
		},

		sync_disabled: {
			retain: 0,
			memory: ''
		},

		paging: false,
		pane_hovered: 'main',

		font_size: 'regular',

		selected: {},

		selected_quick_ref: [],

		chapterLoadMain: {},
		chapterLoadParallel: {},
		
		init: function() {

			this.chapterLoadMain = $.manageAjax.create('chapterLoadMain', {
				queue: true,
				cacheResponse: false,
				maxRequests: 1
			});
			
			this.chapterLoadParallel = $.manageAjax.create('chapterLoadParallel', {
				queue: true,
				cacheResponse: false,
				maxRequests: 1
			});
			
			// Setup preloaded chapters in main pane
			reader.setup_preloaded_chapters('main');

			// If sync is enabled, set parallel pane reference to that of main
			reader.parallel.book    = reader.main.book;
			reader.parallel.chapter = reader.main.chapter;
			reader.parallel.verse   = reader.main.verse;

			// Set current y positions of reader panes
			reader.set_pos_y('main');
			reader.set_pos_y('parallel');

			// TEMP
			reader.parallel.enabled = false;

			// Turn on parallel pane if needed
			reader.refresh_parallel();

			// Bind reference_suggest to main input reference
			$('#main input.reference').reference_suggest(
				'main',
				{onSelect: function() {}}
			);

			// Add class to selected versions in drop-downs
			$('#main div.versions a.' + reader.main.version).addClass('selected');
			$('#parallel div.versions a.' + reader.parallel.version).addClass('selected');

			$('ul.selected_list a.x').live('click', function(event) {
				event.preventDefault();
				var li = $(this).parent();
				var book = li.attr('class');
				var confirm_response = confirm('Are you sure you want to remove this selection?');
				if (confirm_response) {
					reader.book_deselected(book);
					$('ul.selected_list li.'+book).remove();
				}
			});

			// Modify HREF's on browse buttons so that
			// they don't interfere with global reference links
			$('a.browse').attr('href', 'javascript:;');

			// Update sync button state
			if (reader.parallel.sync == true) {
				$('a#sync_scrolling').css();
				$('a#unsync_scrolling').show();
			}

			// TODO: See if parallel mode was left on, if so, AJAX request it's data
			if (reader.parallel.enabled === true) {
				//reader.sync_disable();
				reader.chapters_load(reader.parallel.book + '.' + reader.parallel.chapter, 'parallel', false, true, true);
			}

			$('div.reference form').submit(function(event) {
				event.preventDefault();

				var reference = $(this).find('input.reference');
				var reference_check = $(this).find('input.reference_check');

				if (reference.val() == reference_check.val())
				{
					return;
				}

				reference_check.val(reference.val());
				reader.reference_search(this, event);
			});

			// While readers are synced, we need to know the pane being acted on.
			// Since they might have never hovered over a reader pane, set it based on form they're in
			$('input.reference').focus(function(event) {
				reader.pane_hovered = $(this).parents('div.reader').attr('id');
			});
			
			$('#main_content, #parallel_content')
				.click(function(event) {
					var target = $(event.target);
					var type = event.type;
					event.preventDefault();

					if (target.is('span.verse')) {
						reader.verse_selected(target);
					} else if (target.is('strong')) {
						reader.verse_selected(target.parents('span'));
					} else if (target.is('span')) {
						reader.verse_selected(target.parents('span'));
					}
				})
				.hover(
					function() {
						reader.pane_hovered = $(this).parent_pane();
						
						reader.scrolled[reader.pane_hovered]();
					},
					function() {
						$('#' + reader.pane_hovered + '_content').blur();
					}
				)
				.bind('scroll.default', function(event) {
					var pane_hovered            = reader.pane_hovered;
					var pane_scrolled           = $(this).parents('div.reader').attr('id');
					var reader_parallel_enabled = reader.parallel.enabled;
					var reader_parallel_sync    = reader.parallel.sync;

					// To prevent this function from running on every
					// in-between state while scrolling use timers
					
					if (typeof($(this).stopTime) == 'function') {
						$(this).stopTime('reference_input');
					}

					$(this).oneTime(500, 'reference_input', function() {
						var pane = reader.refresh_reference_input(this, pane_hovered);

						reader.set_browse(pane);

						if ((reader_parallel_enabled == true && reader_parallel_sync == true) && ((pane == 'main' && pane_hovered == 'main')/* || (pane == 'parallel' && pane_hovered == 'parallel')*/)) {
							reader.sync(pane, true);
						}
					});

					// Before updating reader y position, set previous y position
					// we need both to determine scroll direction
					reader[pane_scrolled].pos_y.previous = reader[pane_scrolled].pos_y.current;
					reader.set_pos_y($(this).parent_pane());
				});

			// Remove any href's from links you don't want intercepted
			$('a.prev_reader, a.next_reader').attr('href', 'javascript:;');

			// Scroll to actual chapter requested
			var position
				= (reader.main.verse === '1')
				? reader.main.book + '_' + reader.main.chapter
				: reader.main.book + '_' + reader.main.chapter + '_' + reader.main.verse;
		},

		post_init: function() {
			// This 1 ms delay fixes the initial scroll-to bug in IE
			$(this).oneTime(1, function() {
				reader.scroll_to_reference('main', reader.main.book + '_' + reader.main.chapter + '_' + reader.main.verse, false, true);
			});
		},

		chapters_load: function(chapter, pane, prepend, refresh, set_copyright, scroll_to, caller) {
			if (typeof(reader[pane]) !== 'undefined') {
				refresh = (typeof(refresh) === 'undefined' || refresh === false) ? false : true;
				scroll_to = (typeof(scroll_to) === 'undefined' || scroll_to === false) ? false : scroll_to;

				if (pane === 'main') {
					var chapterLoadAjax = this.chapterLoadMain;
				} else {
					var chapterLoadAjax = this.chapterLoadParallel;
				}
				
				chapterLoadAjax.add({
					dataType: 'jsonp',
					password: config.password,
					error: function (xhr, status, error) {
						alert(config.errors.unexpected);	
					},
					success: function(data) {
						if (data.response.code === 200) {
							data = data.response.data[0].data;

							var html_f = '';
							var temp_html = '';

							if (refresh === true) {
								// Clear out loaded and setup previous/next
								reader[pane].loaded   = [];
								reader[pane].previous = (data.previous !== '') ? data.previous.reference.osis : '';
								reader[pane].next     = (data.next !== '') ? data.next.reference.osis : '';

								if (data.before !== '')
								{
									reader[pane].loaded.unshift(data.before.reference.osis);

									temp_html = $(data.before.content)[0];
									$(temp_html).attr('id', pane + '_' + data.before.reference.osis.osis_to_css_style());
									html_f += $(temp_html).parent().html();
								}

								reader[pane].loaded.push(data.request.reference.osis);

								temp_html = $(data.request.content)[0];
								$(temp_html).attr('id', pane + '_' + data.request.reference.osis.osis_to_css_style());
								html_f += $(temp_html).parent().html();

								if (data.after !== '')
								{
									reader[pane].loaded.push(data.after.reference.osis);

									temp_html = $(data.after.content)[0];
									$(temp_html).attr('id', pane + '_' + data.after.reference.osis.osis_to_css_style());
									html_f += $(temp_html).parent().html();
								}

								// Load HTML into DOM
								$('#' + pane + '_content > div').html(html_f);

								// Scroll to scripture
								reader.scroll_to_reference(pane, chapter, false, true);
							} else {
								if (prepend === true && data.before !== '') {
									reader[pane].loaded.unshift(data.request.reference.osis);
									reader[pane].previous = (data.previous !== '') ? data.previous.reference.osis : '';

									html_f = $(data.request.content)[0];
									$(html_f).attr('id', pane + '_' + data.request.reference.osis.osis_to_css_style());

									var content = $('#' + pane + '_content');
									var content_container = $('#' + pane + '_content_container');
									var height_original = content_container.height();
									var scrolltop_original = content.scrollTop();

									content_container.prepend(html_f);

									content.scrollTop(scrolltop_original + (content_container.height() - height_original));
								} else if (prepend === false && data.after !== '') {
									var content           = $('#' + pane + '_content');
									var content_container = $('#' + pane + '_content_container');
									var content_container_height = content_container.height();

									reader[pane].loaded.push(data.request.reference.osis);
									reader[pane].next = (data.next !== '') ? data.next.reference.osis : '';

									html_f = $(data.request.content)[0];
									$(html_f).attr('id', pane + '_' + data.request.reference.osis.osis_to_css_style());

									$('#' + pane + '_content_container').append(html_f);

									var chapter_height = content_container.height() - content_container_height;
									reader[pane].loading_in_height += chapter_height;
									
									// TODO: Test and see if this actually even makes a real difference, if not remove it
/*									if (reader[pane].loading_in_height < content.height()) {
										reader.chapters_load(reader[pane].next, pane, prepend, false, false, false);
									} else {
										reader[pane].loading_in_height = 0;
									}*/
								}

								if (scroll_to === true) { // Scroll to chapter just loaded
									reader.scroll_to_reference(pane, data.request.reference.osis);
								} else if (scroll_to !== false) { // Scroll to reference specified
									reader.scroll_to_reference(pane, scroll_to);
								}

								
								// Since we loaded in a chapter, call unload to see if we need to unload anything
								if (caller === 'paging') {
 									if (reader[pane].scrolling === false) {
										reader.chapters_unload(pane, prepend);
									} else {
										$(this).everyTime(100, 'chapters_unload_' + chapter, function() {
											if (reader[pane].scrolling === false) {
												$(this).stopTime('chapters_unload_' + chapter);
												reader.chapters_unload(pane, prepend); // For some reason this scrollTop adjustment when paging does not work correctly
											}
										});
									}
									reader.paging = false;
								} else {
									reader.chapters_unload(pane, prepend);
								}
							}

							if (set_copyright === true) {
								reader.set_copyright(data.copyright, pane);
							}

							reader.verse_reselection(pane);

							if (caller !== 'paging') {
								//reader.sync(pane);
							}

						} else if (data.response.code === 404) {
							// TODO: Handle 404 in a more elegant way
							alert(config.errors.unexpected);
						}
					},
					type: 'GET',
					username: config.username,
					url: youversion.api_url + '1.1/bible/chapter.json?version=' + reader[pane].version + '&reference=' + chapter + '&format=html&adjacent=' + refresh
				});
			}
		},

		chapters_unload: function(pane, prepend, last) {
			var content = $('#' + pane + '_content');
			var content_container = $('#' + pane + '_content_container');

			var top_chapter = content_container.find('> div:first-child');
			var bottom_chapter = content_container.find('> div:last-child');

			var cc_height = content_container[0].offsetHeight;
			var tc_height = top_chapter[0].offsetHeight;
			var bc_height = bottom_chapter[0].offsetHeight;
			
			if (reader[pane].loaded.length >= 10) {
				if (prepend === true) { // New chapters were added to top, so remove old from bottom
					if ( ((bc_height < cc_height / 3) && tc_height > bc_height) || bc_height < cc_height / 10 ) {
						reader[pane].next = reader[pane].loaded.pop();
						var div = document.getElementById(pane + '_' + reader[pane].next.osis_to_css_style());
						div.parentNode.removeChild(div);
						
						if (reader[pane].loaded.length >= 10 && last !== true) {
							reader.chapters_unload(pane, prepend, true);
						}
					}
				} else { // New chapters were added to bottom, so remove old from top					
					//console.log(bottom_chapter.height(), bc_height);
					if ( ((tc_height < cc_height / 3) && bc_height > tc_height) || tc_height < cc_height / 10 ) {
						var scrolltop_original = content.scrollTop();

						reader[pane].previous = reader[pane].loaded.shift();
						var div = document.getElementById(pane + '_' + reader[pane].previous.osis_to_css_style());
						div.parentNode.removeChild(div);

						content.scrollTop(scrolltop_original - (cc_height - content_container.height()));
						
						if (reader[pane].loaded.length >= 10 && last !== true) {
							reader.chapters_unload(pane, prepend, true);
						}
					}
				}
			}

			return true;
		},

		osis: function(pane, separator) {
			return reader[pane].book + separator + reader[pane].chapter + separator + reader[pane].verse;
		},

		parallel_toggle: function(refresh) {
			if (refresh === true) {
				reader.parallel.enabled = (reader.parallel.enabled === false) ? true : false;
			}

			if (reader.parallel.enabled === false) {
				reader.parallel.enabled = true;
				reader.parallel.sync    = true;
				meta.journal_modal_hide();
				meta.journal_form_modal_hide();
				meta.contribution_modal_hide();
				$('#meta').hide();
				$('#parallel input.reference').addClass('loading');
				$('#parallel').show();
				$('#parallel-open').addClass('depressed');

				// Setup reference_suggest on parallel
				$('#parallel input.reference').reference_suggest(
					'parallel',
					{onSelect: function() {}}
				);

				if (typeof(refresh) === 'undefined' && reader.parallel.sync === true) {
					//reader.sync('main');
					reader.version_load('parallel', 'main');
				}
			} else {
				reader.parallel.enabled = false;
				reader.parallel.sync    = false;
				$('#parallel').hide();
				$('#parallel input.reference, #parallel input.reference_check').val('');
				$('#meta').show();
				$('#parallel-open').removeClass('depressed');
			}

			reader.save_settings();
		},

		reference_search: function(form, event) {
			var pane  = $(form).parent_pane();
			$('#' + pane + '_content').focus();
			var input = $('#' + pane + ' input.reference');
			var reference_original = event.target.reference.value;
			input.removeClass('error');
			input.addClass('loading');

			var reference = reference_original.human_to_osis(reader[pane].books.human_to_osis, '.');

			var error = false;
			if (reference === false) {
				error = true;
				reference_t = reference_original.replace(/\s+/g, '.');
				if (reference_t.is_osis() === true) {
					error = false;
					reference = reference_t;
				}
			}

			if (error === false) {
				// Lets see if it's a valid chapter for this book
				var osis = reference.split('.');

				if (typeof(reader[pane].books.osis_to_human[osis[0]]) !== 'undefined' && osis[1] > reader[pane].books.osis_to_human[osis[0]][1]) {
					error = true;
				}
			}

			if (error === true) {
				input.removeClass('loading').addClass('error');
				reader[pane].reference_error = true;
				return;
			}

			var reference_css = reference.osis_to_css_style();

			// First lets see if the verse is already loaded in the reader
			var verse = $('#' + pane + '_content .' + reference_css);

			if (verse.length > 0) { // Verse found, scroll to it.
				if (verse.is('span')) { // Only highlight if seeking to individual verse
					if (reader.parallel.enabled === true && reader.parallel.sync === true) {
						reader.verse_highlighted(reference_css, true);
					} else {
						reader.verse_highlighted(reference_css, pane);
					}
				}

				var distance = $('#'+pane+'_content').scrollTop() + $(verse).position().top - 1;

				reader.scroll_action(pane, distance);

				$('#main input.reference').val(reference.osis_to_human());

				input.removeClass('loading');

			} else { // Verses not loaded in, load them in and seek to
				if (reader.parallel.enabled === true && reader.parallel.sync === true) { // Sync is on, load in both panes
					reader.chapters_load(reference, pane, false, true);
					reader.chapters_load(reference, pane.opposite_pane(), false, true);
				} else { // Just load in pane requested
					reader.chapters_load(reference, pane, false, true);
				}
			}
		},

		verse_highlighted: function(reference, pane)
		{
			if (pane === true) {
				var verse = $('div.reader .' + reference);
				verse.css({backgroundColor: '#D9EBFD'});
				$(this).oneTime(2500, function() {
					verse.animate({backgroundColor: '#FFFFFF'}, 750, 'easeOutCubic', function() { verse.css({backgroundColor: ''})});
				});
			} else {
				var verse = $('#' + pane + ' .' + reference);
				verse.css({backgroundColor: '#D9EBFD'});
				$(this).oneTime(2500, function() {
					verse.animate({backgroundColor: '#FFFFFF'}, 750, 'easeOutCubic', function() { verse.css({backgroundColor: ''})});
				});
			}
		},

		refresh_parallel: function()
		{
			reader.parallel_toggle(true);
		},

		refresh_reference_input: function(pane_content, pane_hovered)
		{
			var pane = $(pane_content).parent_pane();
			var content_top = $(pane_content).offset().top;
			var pane_opposite = (pane === 'main') ? 'parallel' : 'main';

			if (reader[pane].reference_error === true) {
				$('#' + pane + ' input.reference').removeClass('error');
				reader[pane].reference_error = false;
			}

			$('#' + pane + ' input.reference').removeClass('loading');

			if (pane !== pane_hovered) {
				reader[pane].book    = reader[pane_opposite].book;
				reader[pane].chapter = reader[pane_opposite].chapter;
				reader[pane].verse   = reader[pane_opposite].verse;

				$('#' + pane + ' input.reference, #' + pane + ' input.reference_check').val(reader[pane].books.osis_to_human[reader[pane].book][0] + ' ' + reader[pane].chapter + ':' + reader[pane].verse);
				$('#' + pane + ' div.reference h2').html($('#' + pane + ' input.reference').val());
			} else {
				$.each($(pane_content).find('span.verse'), function(i, verse) {
					if ($(verse).offset().top >= content_top) {
						// Remove verse, selected or spaces from class to help build OSIS reference
						var osis = $(verse).attr('class').replace(/verse|selected|highlighted| /gi, '').split('_');
						reader[pane].book    = osis[0];
						reader[pane].chapter = Number(osis[1]);
						reader[pane].verse   = Number(osis[2]);
						var human = reader[pane].books.osis_to_human[reader[pane].book][0] + ' ' + reader[pane].chapter + ':' + reader[pane].verse;
						$('#' + pane + ' input.reference, div#' + pane + ' input.reference_check').val(human);
						$('#' + pane + ' div.reference h2').html(human);
						document.title = human + ' ' + reader[pane].version.toUpperCase() + ' - YouVersion.com: Online Bible';

						if (reader[pane].book === 'Gen' && reader[pane].chapter === 1 && reader[pane].verse === 1)
						{
							$('#' + pane + ' .prev_reader').addClass('disabled');
						} else {
							$('#' + pane + ' .prev_reader').removeClass('disabled');
						}

						if (reader[pane].book === 'Rev' && reader[pane].chapter === 22 && reader[pane].verse >= 1)
						{
							$('#' + pane + ' .next_reader').addClass('disabled');
						} else {
							$('#' + pane + ' .next_reader').removeClass('disabled');
						}

						return false;
					}
				});
			}

			reader.save_settings();

			return pane;
		},

		scrolled: {
			main: function() {
				var pane_scrolled = 'main';
				var pane_opposite = 'parallel';
	
				reader.unbind_scroll_hover();
	
				$('#main_content').bind('scroll.hover', function() {
	
					// If sync_scrolling is on, keep them lined up.
					if (reader.pane_hovered ==='main' && reader.parallel.sync === true) {
						var content = $('#parallel_content');
						content.scrollTop(content.scrollTop() + ($('#main_content').scrollTop() - reader.main.pos_y.previous));
					}
	
					var content = $('#main_content');
					var content_height = content[0].offsetHeight;
	
					// User scrolling down
					if (reader.main.pos_y.current > reader.main.pos_y.previous && reader[pane_scrolled].next !== '') {

						if (($('#main_content_container')[0].offsetHeight - reader.main.pos_y.current - content_height) < ($('#main_content')[0].offsetHeight * 1.5)) {
							reader.chapters_load(reader.main.next, 'main', false, false);
	
							if (pane_scrolled === 'main' && reader.parallel.sync === true)
							{
								reader.chapters_load(reader.parallel.next, 'parallel', false, false);
							}
						}
	
					// User scrolling up
					} else if (reader.main.pos_y.current < reader.main.pos_y.previous && reader[pane_scrolled].previous !== '') {
	
						if (reader.main.pos_y.current < ($('#main_content')[0].offsetHeight * 1.5)) {
							reader.chapters_load(reader.main.previous, 'main', true, false);
	
							if (reader.parallel.sync === true) {
								reader.chapters_load(reader.parallel.previous, 'parallel', true, false);
							}
						}
	
					}
				});
			},

			parallel: function() {
	
				reader.unbind_scroll_hover();
	
				$('#parallel_content').bind('scroll.hover', function() {
					var content = $('#parallel_content');
					var content_height = content[0].offsetHeight;
	
					// User scrolling down
					if (reader.parallel.pos_y.current > reader.parallel.pos_y.previous) {
	
						if (($('#parallel_content_container')[0].offsetHeight - reader.parallel.pos_y.current - content_height) < ($('#parallel_content')[0].offsetHeight * 1.5)) {
							reader.chapters_load(reader.parallel.next, 'parallel', false, false);
						}
	
						// User scrolling up
					} else if (reader.parallel.pos_y.current < reader.parallel.pos_y.previous) {
	
						if (reader.parallel.pos_y.current < ($('#parallel_content')[0].offsetHeight * 1.5)) {
							reader.chapters_load(reader.parallel.previous, 'parallel', true, false);
						}
	
					}
				});
	
			}
		},

		unbind_scroll_hover: function() {
			$('#main_content, #parallel_content').unbind('scroll.hover');
		},

		scroll_action: function(pane, distance, caller) {
			if (distance !== 0) {
				$('#'+pane+'_content').animate(
					{scrollTop: distance},
					400,
					'easeOutCubic',
					function() {
						reader[pane].scrolling = false;
						if (caller === 'paging') {
							reader.paging = false;
						}
					}
				);
			}
		},

		scroll_to_reference: function(pane, reference, speed, highlight, caller) {
			reader[pane].scrolling = true;
			var reference_range = reference.osis_list_from_range();
			var osis_css = reference.osis_to_css_style();

			var verse = $('#' + pane + ' .' + osis_css);

			speed = (typeof(speed) === 'undefined' || speed === false) ? 400 : Number(speed);

			if (highlight === true) {
				var references = reference.osis_list_from_range();

				$.each(references, function(i, val) {
					reader.verse_highlighted(val, pane);
				});
			}

			if ($(verse).length > 0) {
				var distance = $('#'+pane+'_content').scrollTop() + $(verse).position().top - 1;

				reader.scroll_action(pane, distance, caller);
			}
		},

		set_pos_y: function(pane)
		{
			reader[pane].pos_y.current = $('#' + pane + '_content').scrollTop();
		},

		save_settings: function()
		{
			// To prevent this function from running on every minute action by the user use timers

			// Kill any other instances of set_cookie that are waiting to be run
			if (typeof($(this).stopTime) == 'function')
			{
				$(this).stopTime('save_settings');
			}

			// Set settings (cookie and database)
			$(this).oneTime(6000, 'save_settings', function() {
				user.save_settings();
			});
		},

		set_copyright: function(copyright, pane)
		{
			// Setup footer version name and copyright
			if (copyright !== '') {
				var footer_html = '<a href="/versions/'+reader[pane].version+'">'+$('#' + pane + ' .version .title').text()+'</a><br />Copyright &#169; ' + copyright;
			} else {
				var footer_html = '<a href="/versions/'+reader[pane].version+'">'+$('#' + pane + ' .version .title').text()+'</a>';
			}
			$('#' + pane + ' .copyright').html(footer_html);
		},

		set_browse: function(pane)
		{
			var book = reader[pane].book;
			var chapter = reader[pane].chapter;

			var books = $('#' + pane + ' .browse-modal-content .book ul li');
			var chapters = $('#' + pane + ' .browse-modal-content .chapter ul li');

			books.find('a').removeClass('selected');
			chapters.find('a').removeClass('selected');

			books.find('a[class*='+book+']').addClass('selected');

			chapters.find('a').filter(function(obj) {
				return $(this).text() == chapter;
			}).addClass('selected');
		},

		sync: function(pane, scrolling)
		{
			scrolling = (typeof(scrolling) === 'undefined') ? false : true;

			// Make sure same chapters are loaded in each pane first, unless it's a normal scroll action
			if (reader.main.loaded.compare(reader.parallel.loaded) === true) {
				var verse = $('#' + pane + ' .' + reader.osis(pane, '_'));
				
				if (pane == 'main') {
					var opposite_pane = 'parallel';
				} else {
					var opposite_pane = 'main';
				}
				
				var opposite_verse = $('#' + opposite_pane + ' .' + reader.osis(pane, '_'));

				// Although the verse should always be found if the loaded arrays
				// above matched, go ahead and check to avoid JS errors
				if (opposite_verse.length > 0) {
					// Temporarily disable sync to cut down on "flutter"
					//reader.sync_disable();

					var scroll_distance = $(opposite_verse).position().top - $(verse).position().top;
				
					$('#' + opposite_pane + ' div.content').animate(
						{scrollTop: ($('#' + opposite_pane + ' div.content').scrollTop() + scroll_distance)},
						400,
						'easeOutCubic',
						function() {
							//reader.sync_restore();
						}
					);
				} else {
					reader.chapters_load_sync(pane);
				}
			} else {
				reader.chapters_load_sync(pane);
			}
		},

		version_load: function(pane, read_from_pane)
		{
			var master_pane = pane;
			if (typeof(read_from_pane) !== 'undefined')
			{
				master_pane = read_from_pane;
			}

			var reference  = reader[master_pane].book + '.' + reader[pane].chapter + '.' + reader[pane].verse;
			var index_last = reader[master_pane].length - 1;
			var chapters   = reader[master_pane].loaded.join('+');

			// Temporary disable sync (if on) while loading in content
			//reader.sync_disable();
			
			// Much faster than .remove() or .html('')
			$('#' + pane + '_content_container').get(0).innerHTML = '';
			$('#' + pane + '_content').addClass('loading');
			reader[pane].pos_y.current = 0;
			reader[pane].pos_y.previous = 0;
			
			// We need to grab the booklist for the version being requested
			$.ajax(
			{
				dataType: 'json',
				success: function(data)
				{
					if (data.response.code === 200)
					{
						reader[pane].books = data.response.data.books_osis_human;

						var html_ul = '';
						var el_class = '';
						$.each(data.response.data.books, function(i, book) {
							if (book.osis === reader[pane].book) {
								el_class = ' selected';
							}
							html_ul += '<li><a class="' + book.osis + '_' + book.chapters + el_class + '" href="javascript:;">' + book.human + '</a></li>';
							el_class = '';
						});
						$('#' + pane + ' .browse-modal .book ul').html(html_ul);
						$('#' + pane + ' .browse-modal .book .selected').click();
					}
					else
					{
						alert(config.errors.unexpected);
					}
				},
				type: 'GET',
				url: '/bible/books_version/' + reader[pane].version
			});
			
			$.ajax(
			{
				dataType: 'jsonp',
				password: config.password,
				success: function(data)
				{
					if (data.response.code === 200)
					{
						chapters = data.response.data;

						var html_f = '';
						var temp_html = '';

						// Clear out loaded
						reader[pane].loaded = [];

						$.each(chapters, function(i, chapter)
						{
							if (i === 0 && chapter.data.previous !== '')
							{
								reader[pane].previous = chapter.data.previous.reference.osis;
							}

							if (i === index_last && chapter.data.next !== '')
							{
								reader[pane].next = chapter.data.next.reference.osis;
							}

							reader[pane].loaded.push(chapter.data.request.reference.osis);

							temp_html = $(chapter.data.request.content)[0];
							$(temp_html).attr('id', pane + '_' + chapter.data.request.reference.osis.osis_to_css_style());
							html_f += $(temp_html).parent().html();
						});

						reader.set_copyright(chapters[0].data.copyright, pane);

						// Load HTML into DOM
						$('#' + pane + '_content').removeClass('loading');
						$('#' + pane + '_content_container').html(html_f);

						// Select previously selected verses
						reader.verse_reselection(pane);

						// Scroll to position user was at before switching versions
						reader.scroll_to_reference(pane, reference, 200);

						reader.reset_height(pane);

						user.save_settings();
					}
					else if (data.response.code === 404)
					{
						// TODO: Handle 404 in a more elegant way
						alert(config.errors.unexpected);
					}
				},
				type: 'GET',
				username: config.username,
				url: youversion.api_url + '1.1/bible/chapter.json?version=' + reader[pane].version + '&reference=' + chapters + '&format=html'
			});
		},

		chapters_load_sync: function(pane)
		{
			var index_last    = reader[pane].loaded.length - 1;
			var chapters      = reader[pane].loaded.join('+');
			var pane_opposite = (pane === 'main') ? 'parallel' : 'main';

			// Much faster than .remove() or .html('')
			$('#' + pane_opposite + '_content_container').get(0).innerHTML = '';
			$('#' + pane_opposite + '_content').addClass('loading');

			$.ajax(
			{
				dataType: 'jsonp',
				password: config.password,
				success: function(data)
				{
					if (data.response.code === 200)
					{
						chapters = data.response.data;

						var html_f = '';
						var temp_html = '';

						// Clear out loaded
						reader[pane_opposite].loaded = [];

						$.each(chapters, function(i, chapter)
						{
							if (i === 0 && chapter.previous !== '')
							{
								reader[pane_opposite].previous = chapter.previous.reference.osis;
							}

							if (i === index_last && chapter.next !== '')
							{
								reader[pane_opposite].next = chapter.next.reference.osis;
							}

							reader[pane_opposite].loaded.push(chapter.request.reference.osis);

							temp_html = $(chapter.request.content)[0];
							$(temp_html).attr('id', pane_opposite + '_' + chapter.request.reference.osis.osis_to_css_style());
							html_f += $(temp_html).parent().html();
						});

						// Load HTML into DOM
						$('#' + pane_opposite + '_content').removeClass('loading');
						$('#' + pane_opposite + '_content_container').html(html_f);

						// Now try to sync
						reader.sync(pane, true);
					}
					else if (data.response.code === 404)
					{
						// TODO: Handle 404 in a more elegant way
						alert(config.errors.unexpected);
					}
				},
				type: 'GET',
				username: config.username,
				url: youversion.api_url + '1.1/bible/chapter.json?version=' + reader[pane_opposite].version + '&reference=' + chapters + '&format=html'
			});
		},

		setup_preloaded_chapters: function(pane)
		{
			var chapters = $('#' + pane + '_content_container').find('h1');

			$.each(chapters, function(i, chapter)
			{
				var chapter = $(chapter);
				var osis    = chapter.attr('class');

				chapter.parent().attr('id', pane + '_' + osis.osis_to_css_style());
			});
		},

		select_verse: function(reference) {
			reference = reference.osis_to_css_style();
			var verse = $('#main_content_container span.'+reference);
			if (verse.length > 0) {
				reader.verse_selected(verse);
			}
		},

		verse_selected: function(item)
		{
			// Clear out any backgroundColor that may be
			// caused by initial blue highlighting
			item.css({'background-color': ''});

			// Re-setup current action modal
			meta.action_function();			

			var reference = item.attr('class').replace(/verse|selected|highlighted| /gi, '');
			var osis    = reference.split('_');
			var book    = osis[0];
			var chapter = osis[1];
			var verse   = osis[2];

			var selected_index = $.inArray(reference, reader.selected_quick_ref);

			if (selected_index !== -1) // Verse was already selected, deselect
			{
				reader.selected_quick_ref.splice(selected_index, 1);
				if ($('#journal-create-update').is(':visible')) {
					ref_suggest.removeValues(book+'.'+chapter+'.'+verse);
				}
				delete reader.selected[book][chapter][verse];

				var chapter_empty = true;
				$.each(reader.selected[book][chapter], function(i, verse)
				{
					if (typeof(verse) !== 'undefined')
					{
						chapter_empty = false;
					}
				});

				if (chapter_empty === true)
				{
					delete reader.selected[book][chapter];
				}

				var book_empty = true;
				$.each(reader.selected[book], function(i, chapter)
				{
					if (typeof(chapter) !== 'undefined')
					{
						book_empty = false;
					}
				});

				if (book_empty === true)
				{
					delete reader.selected[book];
				}

				$('span.' + reference).removeClass('highlighted').removeClass('selected');
			}
			else // Verse not selected, select it
			{
				if (typeof(reader.selected[book]) === 'undefined')
				{
					reader.selected[book] = [];
					reader.selected[book][chapter] = [];
					reader.selected[book][chapter][verse] = true;
				}
				else
				{
					if (typeof(reader.selected[book][chapter]) === 'undefined')
					{
						reader.selected[book][chapter] = [];
						reader.selected[book][chapter][verse] = true;
					}
					else
					{
						reader.selected[book][chapter][verse] = true;
					}
				}

				reader.selected_quick_ref.push(reference);
				if ($('#journal-create-update').is(':visible')) {
					ref_suggest.addValues(book+'.'+chapter+'.'+verse);
				}
				$('span.' + reference).removeClass('highlighted').addClass('selected');
			}

			// Re-setup action modals
			meta.setup_tag_create();
			meta.setup_bookmark_create();
			meta.setup_link_create();

			if (reader.selected_quick_ref.length > 0) {
				$('#selected_list_all').show();

				reader.selected_plus_string = '';
				if (reader.selected_quick_ref.length > 0) {
					reader.selected_plus_string = reader.selected_quick_ref.join('+').replace(/_/g, '.')
				}

				meta.contributions_community_load(reader.selected_plus_string);
		
				if (SIGNED_IN === true) {
					meta.contributions_my_load(reader.selected_plus_string);
					meta.journals_load(reader.selected_plus_string);
				}
			} else {
				$('#selected_list_all').hide();
			}

			reader.refresh_selected_list();
		},

		refresh_selected_list: function() {
			var html_f = '';
			var html_temp = '';
			var current_chapter = '';
			var book_i = 0;
			var chapter_i = 0;
			var verse_i = 0;
			var verse_previous = false;
			var in_range = false;

			$.each(reader.selected, function(book, chapters)
			{
				var book_orig = book;
				book = reader.main.books.osis_to_human[book][0];

				chapter_i = 0;
				$.each(chapters, function(chapter, verses)
				{
					if (typeof(verses) !== 'undefined')
					{
						html_temp += (chapter_i > 0) ? ('; ' + chapter + ':') : (book + ' ' + chapter + ':');

						verse_i = 0;
						verse_previous = false;
						in_range = false;
						verse_added = false;
						$.each(verses, function(verse, value)
						{
							if (typeof(value) !== 'undefined')
							{
								if (verse_i > 0)
								{
									if (verse === verse_previous + 1) // Falling in a range, set it and get out
									{
										in_range = true;
									}
									else
									{
										if (in_range === true) // Were in range, so lets close it since we no longer are
										{
											html_temp += '-' + verse_previous;
											in_range = false;
										}
										else // Not in range, append comma with verse
										{
											html_temp += ',' + verse;
											in_range = false;
										}
									}
								}
								else // First verse selected in chapter, append verse only
								{
									html_temp += verse;
									in_range = false;
								}

								verse_previous = verse;
								verse_i++;
							}
							else // Empty verse placeholder so if we were in range, we aren't anymore, close it
							{
								if (in_range === true)
								{
									html_temp += '-' + verse_previous;
									in_range = false;
								}
							}
						});

						// To close the last range in iteration of verses, see if we were in a range
						html_temp += (in_range === true) ? ('-' + verse_previous) : '';

						chapter_i++;
					}
				});

				html_f += '<li class="'+book_orig+'"><span>' + html_temp + '</span><a class="x" href="javascript:;">X</a></li>';
				html_temp = '';

				book_i++;
			});

			$('#selected_list_container .selected_list').html(html_f);

			// TODO: Only do this if it's visible
			meta.setup_selected();
		},

		/**
		 * @abstract Useful for reselecting all verse spans
		 * that are selected when loading in chapters
		 *
		 * @param pane string The reading pane to limit scope
		 */
		verse_reselection: function(pane)
		{
			$.each(reader.selected_quick_ref, function(i, verse)
			{
				$('#' + pane + ' span.' + verse).removeClass('highlighted').addClass('selected');
			});
		},

		book_deselected: function(book) {
			// Loop over selected_quick_ref to determine which items need to be removed
			var items_to_delete = [];
			$.each(reader.selected_quick_ref, function(i, verse) {
				if (verse.indexOf(book) >= 0) {
					items_to_delete.push(verse);
					$('div.reader span.'+verse).removeClass('selected');
				}
			});

			$.each(items_to_delete, function(i, val) {
				reader.selected_quick_ref.splice($.inArray(val, reader.selected_quick_ref), 1);
			});

			// Now remove it from the main object
			delete reader.selected[book];

			// If no more in array, close thickbox
			if (reader.selected_quick_ref.length === 0) {
				tb_remove();
				meta.action_modal_close_except('');
				$('#selected_list_all').hide();
			} else {
				meta.setup_selected();
			}
		},

		reset_height: function(pane) {
			if ($.browser.msie) {
				$('#'+pane+'_content').css({'height':'0px'}).css({'height':'auto'});
			}
		}
	};

	// Meta

	var meta =
	{
		contributions_community: {},
		contributions_my: {},
		journals: {},

		// Store data for current modal
		contribution: {},
		journal: {},

		has_focus: '',

		widgets: [],

		action_function: function() {},
		
		link_clips: [],

		init: function()
		{
			if (contributions_community.code === 200) {
				meta.contributions_community = contributions_community.data.contributions;
			}

			if (contributions_my.code === 200) {
				meta.contributions_my = contributions_my.data.contributions;
			}

			if (journals.code === 200) {
				meta.journals = journals.data.journals;
			}

			// Temp for internal launch
			//$('#contrib .footer-inner').find('.nav, .position').hide();

			$('div.meta > .content').hover(
				function() {
					// This basically is just here to remove
					// focus from reader panes when on meta
					$(this).focus();
				},
				function() {}
			);

			var widgets_el = $('ul#widgets');

			widgets_el.sortable({
				handle: 'div.strip div.handle',
				opacity: 0.8
			});
			widgets_el.sortable('disable');

			$('div#organize a.ibutton').click(function() {
				widgets_el.addClass('sorting');
				$('div#organize').hide();
				$('div#organizing').show();
				widgets_el.sortable('enable');
			});

			var closeOrganize = function() {
				widgets_el.removeClass('sorting');
				$('div#organize').show();
				$('div#organizing').hide();
				widgets_el.sortable('disable');
				meta.setup_widgets();
			};

			$('#meta-action-tag form').submit(function(event) {
				event.preventDefault();
				meta.tag_create($(this));
			});

			$('#meta-action-bookmark form').submit(function(event) {
				event.preventDefault();
				meta.bookmark_create($(this));
			});

			$('#meta_actions').find('.tag, .bookmark, .link, .share').click(function(event) {
				event.preventDefault();
				var action = $(this).text().toLowerCase();
				var action_modal = '#meta-action-'+action;

				if ($(action_modal).is(':visible')) {
					var show = false;
				} else {
					var show = true;
				}

				// Close them all, we will open the correct one if necessary
				$('#meta-action-containers > div').hide();
				if (action == 'link') {
					meta.remove_link_clips();
				}
				meta.action_function = function() {};

				$('#meta_actions a').removeClass('depressed');

				if (show === true) {
					switch(true) {
						case (action === 'tag'):
							meta.action_function = meta.setup_tag_create;
							meta.setup_tag_create();
							break;
						case (action === 'bookmark'):
							meta.action_function = meta.setup_bookmark_create;
							meta.setup_bookmark_create();
							break;
						case (action === 'link'):
							meta.action_function = meta.setup_link_create;
							meta.setup_link_create();
							break;
					}

					$(this).addClass('depressed');
					$('#meta-action-'+action).show();
					
					if (action === 'link') {
						meta.add_link_clips();
					}
				}
			});

			$('#meta-action-containers a.use-current').click(function(event) {
				reader.select_verse(reader.main.book+'_'+reader.main.chapter+'_'+reader.main.verse);
			});

			$('#selected_list_all').click(function(event) {
				event.preventDefault();
				var modal = $('#meta-action-selected');
				
				if (modal.data('enabled') == true) {
					meta.close_selected();
				} else {
					meta.show_selected();
				}
			});

			$('#meta-action-containers a.cancel, #meta-action-containers a.ok').click(function(event) {
				event.preventDefault();
				var action = $(this).parents('.modal-box').attr('id').replace('meta-action-', '');
				$('#meta_actions a.'+action).removeClass('depressed');
				$('#meta-action-'+action).hide();
			});

			$('div#organizing a.ibutton.cancel').click(closeOrganize);

			$('#form_widget_control input').change(function() {
				var widget_id = $(this).attr('id');
				widget_id = widget_id.replace('control_', 'meta_');

				if ($('#'+widget_id).data('enabled') == false)
				{
					$('#'+widget_id).data('enabled', true);
					$('#'+widget_id).css({'display': 'block'});
				}
				else
				{
					$('#'+widget_id).data('enabled', false);
					$('#'+widget_id).css({'display': 'none'});
				}

				// TODO: Ajax and save to user which widgets are open and order
			});

			$('#meta_contribs_community a.title').live('click', function(event) {
				event.preventDefault();
				meta.contribution_load(this, 'community');
			});

			$('#meta_contribs_my a.title').live('click', function(event) {
				event.preventDefault();
				meta.contribution_load(this, 'my');
			});

			$('#meta_journal a.title').live('click', function(event) {
				event.preventDefault();
				meta.journal_load(this);
			});

			$('#meta_contribs_my a.reader-contribute').click(function(event) {
				event.preventDefault();
				window.location = config.site_protocol+'://'+config.site_domain_www+'/my/contributions/create/'+reader.selected_plus_string;
			});

			$('#meta_journal a.reader-journal-create').click(function(event) {
				event.preventDefault();
				if (SIGNED_IN === false) {
					user.sign_in();
					return;
				}
				meta.journal_form_modal_load();
			});

			$('#meta_contribs_community div.view-more a').live('click', function(event) {
				event.preventDefault();
				window.location = config.site_protocol+'://'+config.site_domain_www+'/contributions/'+reader.selected_plus_string;
			});

			$('#meta-action-link input.text').live('click', function(event) {
				$(this).select();
			});

			$('#contrib, #journal').find('.footer .go-back').click(function(event) {
				event.preventDefault();
				if ($('#contrib').data('enabled') === true) {
					meta.contribution_modal_hide();
				}
				if ($('#journal').data('enabled') === true) {
					meta.journal_modal_hide();
				}
				meta.meta_modal_show();
			});

			$('#meta_reading_plan .prev, #meta_reading_plan .next').click(function(event) {
				event.preventDefault();
				var rclass = $(this).attr('class');
				var day = rclass.replace(/\s?(?:next|prev)\s?/, '').replace('day_', '');
				meta.reading_plan_load('Robert Roberts', day);
			});

			$('#show_more_less a').toggle(
				function() {
					$('#meta_contribs_community div.content').addClass('show-more');
					$(this).removeClass('reader-show-more').addClass('reader-show-less').text('Show Less');
				},
				function() {
					$('#meta_contribs_community div.content').removeClass('show-more');
					$(this).removeClass('reader-show-less').addClass('reader-show-more').text('Show More');
				}
			);

			// Setup actions for contrib modal
			$('#contrib .like a').click(function(event) {
				var that = this;
				if ($(that).text() !== 'Like') {
					return false;
				}

				$(that).addClass('loading');

				if (SIGNED_IN === false) {
					user.sign_in();
					$(that).removeClass('loading');
					return;
				}

				if ($('#contrib').hasClass('community')) {
					var array_id = $('#contrib').removeClass('community').attr('class').replace('contribution_', '');
					var contribution_li = $('#meta_contribs_community li a.contribution_'+array_id).parent();
					id = meta.contributions_community[array_id].id;
				} else if ($('#contrib').hasClass('my')) {
					var array_id = $('#contrib').removeClass('my').attr('class').replace('contribution_', '');
					var contribution_li = $('#meta_contribs_my li a.contribution_'+array_id).parent();
					id = meta.contributions_my[array_id].id;
				}

				$.ajax({
					cache: false,
					dataType: 'json',
					success: function(j) {
						if (j.code === 200) {
							contribution_li.addClass('liked');
							$(that).text('You like this');
						} else {
							
						}
						$(that).removeClass('loading');
					},
					url: '/bible/contribution_like/'+id
				});
			});

			// Widget Reoder & Enable/Disable
			$('#organize-save').click(function(event) {
				var widgets = $('ul#widgets').sortable('toArray');

				$.each(widgets, function(i, widget) {
					widget = widget.replace('meta_', '');

					if ($('#control_'+widget)[0].checked == true) {
						$('#meta_'+widget).show();
						widget += '_enabled';
					} else {
						$('#meta_'+widget).hide();
						widget += '_disabled';
					}

					widgets[i] = widget;
				});

				meta.widgets = widgets;

				widgets_el.removeClass('sorting');
				$('div#organize').show();
				$('div#organizing').hide();
				widgets_el.sortable('disable');

				user.save_settings();
			});

			$('#journal div.edit').click(function(event) {
				var id = $('#journal').attr('class').replace('journal_', '');
				event.preventDefault();
				meta.journal_form_modal_load(id);
			});

			$('#journal-create-update form').bind('keydown', function(event) {
				if (event.keyCode === 13 && meta.has_focus !== 'journal-form-content') {
					event.preventDefault();
					$(this).submit();
				}
			});

			$('#journal-form-content')
				.focus(function(event) {
					meta.has_focus = 'journal-form-content';
				})
				.blur(function(event) {
					meta.has_focus = '';
				});

			$('#journal-create-update a.save').click(function(event) {
				$('#journal-form').submit();
			});

			$('#journal-create-update a.cancel').click(function(event) {
				event.preventDefault();
				meta.journal_form_modal_hide();
				$('#meta').show();
			});

			$('#journal-create-update a.continue').click(function(event) {
				event.preventDefault();
				meta.journal_form_modal_hide();
				$('#meta').show();
			});

			meta.setup_widgets();
		},

		setup_widgets: function() {
			var widgets_stored  = meta.widgets;
			var widgets_current = $('ul#widgets').sortable('toArray');

			$.each(widgets_stored, function(i, val) {
				var widget = val.replace(/_enabled|_disabled/gi, '');

				if (val.indexOf('enabled') >= 0) {
					$('#control_'+widget).attr('checked', 'checked');
					$('#meta_'+widget).show();
				} else {
					$('#control_'+widget).removeAttr('checked');
					$('#meta_'+widget).hide();
				}

				$("ul#widgets").append($("#meta_" + widget));
			});
		},

		meta_modal_show: function() {
			$('#meta').data('enabled', true).show();
		},

		meta_modal_hide: function() {
			$('#meta').removeData('enabled').hide();
		},

		contribution_load: function(contrib, widget) {
			var that = $(contrib);
			var contrib = $(that).parent();
			contrib.addClass('loading');
			var contrib_content = contrib.find('.contrib-content');

			var contributions = [];
			if (widget === 'community') {
				contributions = meta.contributions_community;
			} else if (widget === 'my') {
				contributions = meta.contributions_my;
			}

			var id = that.attr('class').replace('title contribution_', '');

			meta.contribution_modal_load(id, widget);
			contrib.removeClass('loading');
		},

		contribution_modal_load: function(id, widget, refresh) {
			// Load stuff into DOM
			var contributions = [];
			var contrib_data = [];
			if (widget === 'community') {
				contributions = meta.contributions_community;
				meta.contribution = meta.contributions_community[id];
			} else if (widget === 'my') {
				contributions = meta.contributions_my;
				meta.contribution = meta.contributions_my[id];
			}

			var contrib        = $('#contrib');
			contrib.attr('class', '');
			contrib.addClass(widget+' contribution_'+id);
			var contrib_info   = contrib.find('div.contrib-info');
			var contrib_c      = $('#contrib-inner-content');
			var contrib_c_data = $('#contrib-data');
			var contrib_c_text = $('#contrib-text');

			// Only show button if contribution user is user logged in
			if (meta.contribution.user.user_id === user.user_id) {
				if (refresh === true) {
					$('#contrib-edit').attr('href', '/my/contributions/edit/'+meta.contribution.id).parent().fadeIn(500);
				} else {
					$('#contrib-edit').attr('href', '/my/contributions/edit/'+meta.contribution.id).parent().show();
				}
			} else {
				$('#contrib-edit').attr('href', '/my/contributions/edit/'+meta.contribution.id).parent().hide();
			}

			if (meta.contribution.liked == true) {
				contrib.find('li.like a').text('You like this');
			} else {
				contrib.find('li.like a').text('Like');
			}
			contrib.find('li.report a').attr('href', '/contributions/report/'+meta.contribution.id);

			if (refresh !== true) {
				contrib_info.find('h2 a').text(meta.contribution.title);
				contrib_info.find('.user').attr('href', '/users/' + meta.contribution.user.username).text(meta.contribution.user.username);

				var html_ul = '';
				if (typeof(meta.contribution.references_html) == 'undefined') {
					$.each(meta.contribution.references, function(i, val) {
						html_ul += '<li><a href="/bible/'+reader.main.version+'/'+val.osis.osis_to_url()+'">'+val.human+'</a></li>';
					});
					contributions[id].references_html = html_ul;
				} else {
					html_ul = meta.contribution.references_html;
				}
				contrib_info.find('ul.references').html(html_ul);
	
				switch (meta.contribution.type) {
				    case 'video':
				    	contrib_c_data.flash({
				    		height: '344',
				    		swf: 'http://www.youtube.com/v/SHZ9fsusMGc&hl=en&fs=1',
				    		width: '425'
				    	});
				    	break;
				    case 'image':
				    	contrib_c_data.html('<img src="' + meta.contribution.data_url + '"/>');
				    	break;
				    default:
				    	break;
				}
				switch (meta.contribution.type) {
					case 'video':
						switch(meta.contribution.subtype) {
							case 'youtube':
								contrib_c_data.flash({
									height: '344',
									swf: 'http://www.youtube.com/v/'+meta.contribution.data+'&hl=en&fs=1',
									width: '425'
								});
								break;
							case 'vimeo':
								contrib_c_data.flash({
									height: '344',
									swf: 'http://vimeo.com/moogaloop.swf?clip_id='+meta.contribution.data+'&server=vimeo.com&show_title=0&show_byline=0&show_portrait=0&color=00a6e5&fullscreen=1',
									width: '425'
								});
								break;
							case 'lifechurch.tv':
								contrib_c_data.flash({
									swf: 'http://origin1.lifechurch.tv/player/LCPlayer.swf',
									width: '416',
									height: '262',
									params: {
										movie: 'http://origin1.lifechurch.tv/player/LCPlayer.swf',
										allowScriptAccess: 'sameDomain',
										wmode: 'window',
										flashvars: {
											autostart: 'false',
											file: meta.contribution.data.replace('.flv', ''),
											sec: '0',
											showForm: 'true',
											configPath: 'http://origin1.lifechurch.tv/player/'
										},
										quality: 'high'
									}
								});
								break;
							case 'tangle':
								contrib_c_data.flash({
									height: '344',
									swf: 'http://www.tangle.com/flash/swf/flvplayer.swf?viewkey='+meta.contribution.data,
									width: '425'
								});
								break;
						}
						break;
					case 'image':
						contrib_c_data.html('<img src="'+meta.contribution.data_url+'"/>');
						break;
					case 'link':
						contrib_c_data.html('<a href="'+meta.contribution.data_url+'" rel="external">'+meta.contribution.title+'</a>');
						break;
					default:
						contrib_c_data.html('');
						break;
				}

				contrib_c_text.html(meta.contribution.description);

				var nav = $('#contrib .footer-inner .nav');
				
				// Setup nav and position info
				if (contributions.length > 1) {
					nav.find('a').unbind('click');
					if ((contributions.length - 1) === id) {
						nav.find('a.next_reader').addClass('disabled');
					} else {
						nav.find('a.next_reader')
							.removeClass('disabled')
							.click(function() {
								meta.next_contribution(contrib, widget, contributions.length);
							});;
					}
					if (id === 0) {
						nav.find('a.prev_reader').addClass('disabled');
					} else {
						nav.find('a.prev_reader')
							.removeClass('disabled')
							.click(function() {
								meta.prev_contribution(contrib, widget);
							});
					}
				} else {
					nav.find('a.prev_reader, a.next_reader').addClass('disabled');
				}

				$('#contrib .footer-inner .position').text((Number(id) + 1)+' of '+contributions.length);

				// Disable meta
				$('#meta').hide();

				// Setup hotkeys
				$(document).unbind('keydown', 'k');
				$(document).unbind('keydown', 'j');

				$(document).bind('keydown', {combi:'k', disableInInput: true}, function(event) {
					meta.prev_contribution(contrib, widget);
				});
				$(document).bind('keydown', {combi:'j', disableInInput: true}, function(event) {
					meta.next_contribution(contrib, widget, contributions.length);
				});

				// Enable contrib
				$('#contrib').data('enabled', true).show();
			}
		},

		prev_contribution: function(contrib, widget) {
			var cid = contrib.attr('class').replace(widget+' contribution_', '');
			var prev_cid = Number(cid) - 1;
			if (prev_cid >= 0) {
				meta.contribution_modal_load(prev_cid, widget);
			}
		},

		next_contribution: function(contrib, widget, contribs_length) {
			var cid = contrib.attr('class').replace(widget+' contribution_', '');
			var next_cid = Number(cid) + 1;
			if (next_cid < contribs_length) {
				meta.contribution_modal_load(next_cid, widget);
			}
		},

		contribution_modal_hide: function() {
			$(document).unbind('keydown', 'k');
			$(document).unbind('keydown', 'j');
			$('#contrib').removeData('enabled').hide();
		},

		contributions_community_load: function(references) {
			if (reader.selected_quick_ref.length > 0) {
				$('#meta_contribs_community h3').addClass('loading');

				var ajax_url = (references === '') ? '/bible/contributions_community' : '/bible/contributions_community/'+references

				$.ajax(
				{
					dataType: 'json',
					success: function(j) {
						var total = 0;
						if (j.code === 200) {
							if (typeof(j.data.total) !== 'undefined') {
								total = j.data.total;
							}
							meta.contributions_community = j.data.contributions;
						}

						$('#meta_contribs_community')
							.find('h3').text('Community Contributions ('+total+')').end()
							.find('div.content').html(j.html);

						$('#meta_contribs_community h3').removeClass('loading');
					},
					url: ajax_url
				});
			}
		},

		contributions_my_load: function(references) {
			if (reader.selected_quick_ref.length > 0) {
				$('#meta_contribs_my h3').addClass('loading');

				var ajax_url = (references === '') ? '/bible/contributions_my' : '/bible/contributions_my/'+references

				$.ajax({
					dataType: 'json',
					success: function(j) {
						var total = 0;
						if (j.code === 200) {
							total = (typeof(j.data.total) !== 'undefined') ? j.data.total : total;
							meta.contributions_my = j.data.contributions;
						}

						$('#meta_contribs_my')
							.find('h3').text('My Contributions ('+total+')').end()
							.find('div.content').html(j.html);

						$('#meta_contribs_my h3').removeClass('loading');
					},
					url: ajax_url
				});
			}
		},

		journal_load: function(journal) {
			var that = $(journal);
			var journal = $(that).parent();
			journal.addClass('loading');
			var journal_content = journal.find('.journal-content');

			var id = that.attr('class').replace('title journal_', '');

			meta.journal_modal_load(id);
			journal.removeClass('loading');
		},

		journal_modal_load: function(id) {
			// Load stuff into DOM
			var journals = [];
			var journal_data = [];

			journals = meta.journals;
			meta.journal = meta.journals[id];

			var journal      = $('#journal');
			journal.attr('class', '');
			journal.addClass('journal_'+id);
			var journal_info = journal.find('div.journal-info');
			var journal_c    = $('#journal-inner-content');
			var journal_text = $('#journal-text');

			// Hide form initially
			$('#form_journal').hide();

			journal_info.find('h2 a').text(meta.journal.title);

			var html_ul = '';
			if (typeof(meta.journal.references_html) == 'undefined') {
				$.each(meta.journal.references, function(i, val) {
					html_ul += '<li><a href="/bible/'+reader.main.version+'/'+val.osis.osis_to_url()+'">'+val.human+'</a></li>';
				});
				journals[id].references_html = html_ul;
			} else {
				html_ul = meta.journal.references_html;
			}
			journal_info.find('ul.references').html(html_ul);

			journal_text.html(meta.journal.body_text);

			// Setup nav and position info
			var nav = journal.find('.footer-inner .nav');
			if (journals.length > 1) {
				nav.find('a').unbind('click');
				if ((journals.length - 1) === id) {
					nav.find('a.next_reader').addClass('disabled');
				} else {
					nav.find('a.next_reader')
						.removeClass('disabled')
						.click(function() {
							meta.next_journal(journal, journals.length);
						});;
				}
				if (id === 0) {
					nav.find('a.prev_reader').addClass('disabled');
				} else {
					nav.find('a.prev_reader')
						.removeClass('disabled')
						.click(function() {
							meta.prev_journal(journal);
						});
				}
			} else {
				nav.find('a.prev_reader, a.next_reader').addClass('disabled');
			}

			journal.find('.footer-inner .position').text((Number(id) + 1)+' of '+journals.length);

			meta.meta_modal_hide();
			meta.journal_modal_show();
		},

		journal_form_modal_load: function(id) {
			var journal_modal_title = 'Create Journal';
			var journal_id      = '';
			var journal_title   = '';
			var journal_content = '';

			// Load title/content if updating
			if (typeof(id) !== 'undefined') {
				journal_modal_title = 'Edit Journal';
				journal_id          = meta.journals[id].id;
				journal_title       = meta.journals[id].title;
				journal_content     = meta.journals[id].body_text;
			}

			$('#journal-form-title').val(journal_title);
			$('#journal-form-content').val(journal_content);
			$('#journal-form-id').val(journal_id);

			// Setup references
			var references = [];
			if (typeof(id) !== 'undefined') {
				$.each(meta.journals[id].references, function(i, reference) {
					references.push(reference.osis);
				});
				references = references.join(',');
			} else {
				if (reader.selected_quick_ref.length === 0) {
				reader.select_verse(reader.main.book+'_'+reader.main.chapter+'_'+reader.main.verse);
				}
				references = reader.selected_quick_ref.join(',').replace(/_/g, '.');
			}

			var callbacks = [];
			callbacks.push(meta.journal_create);
			ref_suggest.init("input#journal-form-reference-input", "input#journal-form-references", references, 'journal', callbacks);

			$('#journal-create-update div.header h2').text(journal_modal_title);
			$('#journal-form')
				.find('ul.errors').hide().end()
				.find('ul.success').hide();
			$('#journal-create-update')
				.find('.save, .cancel').show().end()
				.find('.continue').hide();

			if (journal_id === '') {
				meta.meta_modal_hide();
			} else {
				meta.journal_modal_hide();
			}
			meta.journal_form_modal_show();
		},

		journal_form_modal_show: function() {
			$(document).unbind('keydown', 'e');
			$(document).unbind('keydown', 'h');
			$(document).unbind('keydown', 'k');
			$(document).unbind('keydown', 'j');

			$('#journal-create-update').data('enabled', true);
			$('#journal-create-update').show();
		},

		journal_form_modal_hide: function() {
			$('#journal-create-update').removeData('enabled').hide();
		},

		journal_create: function() {

			var form = $('#journal-form');

			var journal_create_update = $('#journal-create-update');

			var journal_id = $('#journal-form-id').val();
			var action = '/my/journal/create';
			if (journal_id !== '') {
				action = '/my/journal/edit/'+journal_id;
			}

			journal_create_update
				.find('.save, .cancel, .continue').hide().end()
				.find('.loading').show();

			$.ajax({
				data: form.serialize(),
				dataType: 'json',
				success: function(data) {
					if (data.code === 200) {
						$('#journal-form-id').val(data.data.id);
						form.find('ul.errors:not(.selected_references)').hide();
						journal_create_update
							.find('.loading').hide().end()
							.find('.save, .cancel, .continue, .success').show();

						// Reload journal data
						meta.journals_load(reader.selected_plus_string);
					} else {
						var html_f = '';
						$.each(data.data.errors, function(i, val) {
							html_f += '<li>'+val+'</li>';
						});
						journal_create_update
							.find('.loading').hide().end()
							.find('.save, .cancel').show();
						form.find('ul.errors:not(.selected_references)').html(html_f).show();
					}
				},
				type: form.attr('method'),
				url: action
			});
		},

		prev_journal: function(journal) {
			var jid = journal.attr('class').replace('journal_', '');
			var prev_jid = Number(jid) - 1;
			if (prev_jid >= 0) {
				meta.journal_modal_load(prev_jid);
			}
		},

		next_journal: function(journal, journals_length) {
			var jid = journal.attr('class').replace('journal_', '');
			var next_jid = Number(jid) + 1;
			if (next_jid < journals_length) {
				meta.journal_modal_load(next_jid);
			}
		},

		journal_modal_show: function() {
			// Setup hotkeys
			$(document).unbind('keydown', 'e');
			$(document).unbind('keydown', 'k');
			$(document).unbind('keydown', 'j');

			$(document)
				.bind('keydown', {combi:'e', disableInInput: true}, function(event) {$('#journal div.edit').click();})
				.bind('keydown', {combi:'k', disableInInput: true}, function(event) {meta.prev_journal($('#journal'));})
				.bind('keydown', {combi:'j', disableInInput: true}, function(event) {meta.next_journal($('#journal'), meta.journals.length);});

			$('#journal').data('enabled', true).show();
		},

		journal_modal_hide: function() {
			$(document).unbind('keydown', 'k');
			$(document).unbind('keydown', 'j');
			$('#journal').removeData('enabled').hide();
		},

		journals_load: function(references) {
			$('#meta_journal h3').addClass('loading');

			var ajax_url = (references === '') ? '/bible/journal' : '/bible/journal/'+references

			$.ajax(
			{
				dataType: 'json',
				success: function(j) {
					var total = 0;
					if (j.code === 200) {
						total = j.data.total;
						meta.journals = j.data.journals;
					} else {
						total = 0;
						meta.journals = [];
					}

					if ($('#journal').data('enabled') === true) {
						// Lets see if loaded list already has visible journal in it still
						var jid_new = false;
						if (total > 0) {
							$.each(meta.journals, function(i, journal) {
								if (journal.id === meta.journal.id) {
									jid_new = i;
								}
							});
						}

						if (jid_new === false) {
							total++;
							var jid = $('#journal').attr('class').replace('journal_', '');
							var html_li = $($('#meta_journal div.content ul li').get(jid)).clone();

							if (total === 1) {
								$('#meta_journal div.content ul').empty();
								j.html = $('#meta_journal div.content').html();
							}
						}
					}

					$('#meta_journal')
						.find('h3').text('Journal ('+total+')').end()
						.find('div.content').html(j.html);

					if ($('#journal').data('enabled') === true) {
						// Journal currently reading/updating not in loaded list, append to top
						if (jid_new === false) {
							meta.journals.unshift(meta.journal);
							$('#meta_journal div.content ul').prepend(html_li);
							// Re-number indexes on li's now
							$('#meta_journal div.content ul li').each(function(i, li) {
								$(li).find('a.title').attr('class', 'title journal_'+i);
							});
						// Journal was in list, so just update the indexed position
						} else {
							$('#journal').attr('class', 'journal_'+jid_new);
						}
					}

					$('#meta_journal h3').removeClass('loading');
				},
				url: ajax_url
			});
		},

		reading_plan_load: function(plan, day) {
			$('#meta_reading_plan h3').addClass('loading');
			$.ajax({
				dataType: 'jsonp',
				success: function(data) {
					if (data.response.code === 200) {
						var data = data.response.data[0];

						// Build reading list
						var html_f = '';
						$.each(data.references, function(i, val) {
							html_f += '<li><a href="'+config.site_protocol+'://'+config.site_domain_www+'/bible/' + reader.main.version + '/' + val.reference.osis.osis_to_url() + '">' + val.reference.human + '</a></li>';
						});

						var meta_reading_plan = $('#meta_reading_plan');

						meta_reading_plan
							.find('ul')
								.html(html_f)
								.end()
							.find('h4 > a')
								.text('Day ' + data.day)
								.attr('href', meta_reading_plan.find('h4 > a').attr('href').replace(/[0-9]+$/, data.day))
								.end()
							.find('.prev')
								.attr('href', meta_reading_plan.find('.prev').attr('href').replace(/[0-9]+$/, data.prev))
								.attr('class', 'prev day_' + data.prev)
								.end()
							.find('.next')
								.attr('href', meta_reading_plan.find('.next').attr('href').replace(/[0-9]+$/, data.next))
								.attr('class', 'next day_' + data.next);

					} else {
						// TODO: Handle 404 in a more elegant way
						alert(config.errors.unexpected);
					}

					$('#meta_reading_plan h3').removeClass('loading');
				},
				type: 'GET',
				username: config.username,
				url: youversion.api_url + '1.1/reading_plan/items.json?plan=' + plan + '&day=' + day
			});
		},

		setup_tag_create: function() {
			var meta            = $('#meta-action-tag');
			var form            = meta.find('form');
			var input_reference = $('#meta-action-tag-reference');

			input_reference.val(reader.selected_quick_ref.join('+').replace(/_/g, '.'));

			form.find('ul.errors').hide();

			if (SIGNED_IN === true) {
				meta.find('p.sign-in').hide();
			} else {
				meta.find('p.sign-in').show();
			}

			if (SIGNED_IN === true) {
				if (reader.selected_quick_ref.length > 0) {
					form.find('.success').hide();
					form.show();
					form.parents('div.modal-box').find('p.select-references').hide();
				} else {
					form.hide();
					form.parents('div.modal-box').find('p.select-references').show();
				}
			}
		},

		tag_create: function(form) {
			form.find('.ibutton').hide();
			form.find('.loading').show();
			$.ajax({
				data: form.serialize(),
				dataType: 'json',
				success: function(data) {
					if (data.code === 200) {
						form.find('ul.errors, .loading').hide();
						$('#meta-action-tag-tags').val('');
						form.find('.ibutton, .success').show();
						$(this).oneTime(2000, function() {
							meta.action_modal_close('tag');
						});
					} else {
						var html_f = '';
						$.each(data.data.errors, function(i, val) {
							html_f += '<li>'+val+'</li>';
						});
						form.find('.loading').hide();
						form.find('.ibutton').show();
						form.find('ul.errors:not(.selected_references)').html(html_f).show();
					}
				},
				type: form.attr('method'),
				url: form.attr('action')
			});
		},

		setup_bookmark_create: function() {
			var meta_action     = $('#meta-action-bookmark');
			var form            = meta_action.find('form');
			var input_reference = $('#meta-action-bookmark-reference');
			var input_version   = $('#meta-action-bookmark-version');

			input_reference.val(reader.selected_quick_ref.join('+').replace(/_/g, '.'));
			input_version.val(reader.main.version);

			form.find('ul.errors').hide();

			if (SIGNED_IN === true) {

				meta_action.find('p.sign-in').hide();
				
				if (reader.selected_quick_ref.length > 0) {
					form.find('.success').hide();
					form.show();
					form.parents('div.modal-box').find('p.select-references').hide();
				} else {
					form.hide();
					form.parents('div.modal-box').find('p.select-references').show();
				}
			}
		},

		bookmark_create: function(form) {
			form.find('.ibutton').hide();
			form.find('.loading').show();
			$.ajax({
				data: form.serialize(),
				dataType: 'json',
				success: function(data) {
					if (data.code === 200) {
						form.find('ul.errors, .loading').hide();
						form.find('.ibutton, .success').show();
						$(this).oneTime(2000, function() {
							meta.action_modal_close('bookmark');
						});
					} else {
						var html_f = '';
						$.each(data.data.errors, function(i, val) {
							html_f += '<li>'+val+'</li>';
						});
						form.find('ul.errors:not(.selected_references)').html(html).show();
					}
				},
				type: form.attr('method'),
				url: form.attr('action')
			});
		},

		setup_link_create: function() {			
			if (reader.selected_quick_ref.length > 0) {
				$('#meta-action-link p.select-references').hide();
				$('#meta-action-link form').show();

				var html_ul = '';
				$.each(reader.selected_quick_ref, function(i, val) {
					if (i >= 5) {
						return false;
					}
					html_ul += '<li>'
						+'<input class="text" name="link_'+i+'" value="'+config.site_protocol+'://'+config.site_domain_readly+'/'+val.osis_to_short_url(reader.main.version)+'" type="text" />'
						+'<img src="'+config.site_protocol+'://'+config.site_domain+'/img/page_white_copy.png" alt="Copy to clipboard" title="Copy to clipboard" />'
					+'</li>';
				});

				if (reader.selected_quick_ref.length > 5) {
					html_ul += '<li>*Note: Only first 5 selected verses are shown.</li>';
				}
				
				$('#meta-action-link ul.links').html(html_ul);

				if ($('#meta-action-link').is(':visible') === true) {
					meta.add_link_clips();
				}
			} else {
				$('#meta-action-link form').hide();
				$('#meta-action-link p.select-references').show();
			}
		},

		add_link_clips: function() {
			meta.remove_link_clips();
			
			meta.link_clips = [];
			
			$('#meta-action-link ul.links li img').each(function(i) {
				ZeroClipboard.setMoviePath(config.site_protocol+'://'+config.site_domain+'/js/ZeroClipboard.swf');
                //Create a new clipboard client
                meta.link_clips[i] = new ZeroClipboard.Client();

                // Cache the img and input elements
                var img = $(this);
                var li = img.parent('li');

                //Glue the clipboard client to the img in each li
                meta.link_clips[i].glue(img[0]);

                //Grab the text from the li's input
                var txt = $.trim($('input', li).val());
                meta.link_clips[i].setText(txt);

                //Add a complete event to let the user know the text was copied
                meta.link_clips[i].addEventListener('complete', function(client, txt) {
                	li.append('<span>Copied</span>').find('span').fadeOut('slow');
                });
            });
		},
		
		remove_link_clips: function() {
			if (meta.link_clips.length > 0) {
				$.each(meta.link_clips, function(i, clip) {
					clip.destroy();
				});
				meta.link_clips = [];
			}
		},
		
		setup_selected: function() {
			if (reader.selected_quick_ref.length > 0) {
				$('#meta-action-selected .modal-box-middle').html($('#selected_list_container').html()).end().find('ul.selected_list').css({'float':'none'});
			} else {
				$('#meta-action-selected').hide();
			}
		},

		show_selected: function() {
			$('#meta-action-selected').data('enabled', true).show();
			$('#selected_list_all').text('Close');
		},

		close_selected: function() {
			$('#meta-action-selected').removeData('enabled').hide();
			$('#selected_list_all').text('View All');
		},

		action_modal_close: function(action) {
			if (action == 'link') {
				meta.remove_link_clips();
			}
			$('#meta-action-'+action).hide();
			$('#meta_actions a.'+action).removeClass('depressed');
		},

		action_modal_close_except: function(action) {
			if (action != 'link') {
				meta.remove_link_clips();
			}
			$('#meta-action-containers div.modal-box:not(#meta-action-'+action+')').hide();
			$('#meta_actions a').removeClass('depressed');
		}
	};

// jQuery ready

$(function() {

	initialize();

	// Initialize keyboard shortcuts
	$(document).bind('keydown', {combi:'alt+ctrl+l', disableInInput: true}, function(event) {
		if ($.data(this, 'expose') === true) {
			$.unexpose();
			$.data(this, 'expose', false);
		} else {
			$('div.reader').find('div.header, div.content, div.footer').expose({color:"#000000"});
			$.data(this, 'expose', true);
		}
	});
	$(document).bind('keydown', {combi:'alt+ctrl+p', disableInInput: true}, function(event) {
		reader.parallel_toggle();
	});	
	$(document).bind('keydown', {combi:'h', disableInInput: true}, function(event) {
		if ($('#contrib').data('enabled') === true) {
			meta.contribution_modal_hide();
			$('#meta').show();
			return false;
		}
		if ($('#journal').data('enabled') === true) {
			meta.journal_modal_hide();
			$('#meta').show();
		}
	});

	// Take over any links to references
	$('a[href*="/bible"]').live('click', function(event) {
		event.preventDefault();
		$('#main input.reference').val($(this).attr('href').url_to_human());
		$('#main div.chapter a.selected').removeClass('selected');
		$('#main div.reference form').submit();
	});

	// Take over any sign-in links
	$('a.sign-in').click(function(event) {
		event.preventDefault();
		if (SIGNED_IN === false) {
			user.sign_in();
		}
	});

	$('#parallel-open').click(function()
	{
		reader.parallel_toggle();
	});

	$('div#parallel div.controls a').click(function()
	{
		if (reader.parallel.sync == true)
		{
			$('a#unsync_scrolling').hide();
			$('a#sync_scrolling').show();
			reader.parallel.sync = false;
		}
		else
		{
			$('a#sync_scrolling').hide();
			$('a#unsync_scrolling').show();
			reader.parallel.sync = true;

			// When turning syncing back on,
			// we want to line up parallel pane up with main
			reader.pane_hovered = 'main';
			reader.sync('main');
		}
	});

	$('a.browse').toggle(
		function (e) {
			e.preventDefault();
			$(this).addClass('depressed');
			var browser = $(this).parents('div.reader').find('.browse-modal');
			browser.show();
			var book_scroll_distance = browser.find('.book a.selected').parents('li').position().top;
			var chapter_scroll_distance = browser.find('.chapter a.selected').parents('li').position().top;
			browser.find('.book').scrollTop(book_scroll_distance - 50);
			browser.find('.chapter').scrollTop(chapter_scroll_distance - 50);
		},
		function (e) {
			e.preventDefault();
			var pane = $(this).parent_pane();
			$(this).removeClass('depressed');
			var browser = $(this).parents('div.reader').find('.browse-modal');
			browser.find('.book').scrollTop(0);
			browser.find('.chapter').scrollTop(0);
			browser.hide();
			
			// If clicked on book but not chapter and cancelled, return to previous options.
			if (browser.find('.chapter a.selected').length == 0) {
				browser.find('.book a.selected').removeClass('selected');
				browser.find(".book a[class^='"+reader[pane].book+"']").addClass('selected');
				
				$('#' + pane + ' .browse-modal .chapter li').find('a').filter(function(obj) {
					return $(this).text() == reader[pane].chapter;
				}).addClass('selected');
			}
		}
	);

	$('a.browse, div.browse-modal').hover(
		function(event) {
			$('#' + $(this).parent_pane()).stopTime('browse');
		},
		function(event) {
			var pane = $(this).parent_pane();
			if ($('#'+pane+' div.browse-modal').is(':visible')) {
				$('#'+pane).oneTime(750, 'browse', function() {
					$('#'+pane+' a.browse').click();
				});
			}
		}
	);

	$('a.version').toggle(
		function (e) {
			e.preventDefault();
			$(this).addClass('depressed');
			var versions = $(this).parents('div.reader').find('div.versions-modal');
			versions.show();
			var scroll_distance = versions.find('a.selected').position().top;
			versions.scrollTop(scroll_distance);
		},
		function (e) {
			e.preventDefault();
			$(this).removeClass('depressed');
			var versions = $(this).parents('div.reader').find('div.versions-modal');
			versions.scrollTop(0);
			versions.hide();
		}
	);

	$('a.version, div.versions-modal').hover(
		function(event) {
			$('#' + $(this).parent_pane()).stopTime('versions');
		},
		function(event) {
			var pane = $(this).parent_pane();
			if ($('#'+pane+' div.versions-modal').is(':visible')) {
				$('#'+pane).oneTime(750, 'versions', function() {
					$('#'+pane+' a.version').click();
					//$(this).find('a.version').removeClass('depressed');
					//$(this).find('div.versions-modal').hide();
				});	
			}
		}
	);

	$('#font_size').click(function()
	{
		if (reader.font_size == 'regular') {
			reader.font_size = 'large';
			$('div.reader div.content').css('font-size', '1.2em');
			reader.scroll_to_reference('main', reader.osis('main', '.'), 100);
			$(this).addClass('depressed');
		} else {
			reader.font_size = 'regular';
			$('div.reader div.content').css('font-size', '0.9em');
			reader.scroll_to_reference('main', reader.osis('main', '.'), 100);
			$(this).removeClass('depressed');
		}

		reader.reset_height('main');
		reader.reset_height('parallel');
	});

	$('div.versions a').click(function(event)
	{
		event.preventDefault();

		var version = $(this).attr('class').replace(/selected| /gi, '');
		var lang    = $(this).find('span').attr('lang');
		var pane    = $(this).parent_pane();

		if (version !== reader[pane].version)
		{
			$('#' + pane + ' div.versions a').removeClass('selected');
			$(this).addClass('selected');

			reader[pane].version = version;
			reader.version_load(pane);

			$('#' + pane + ' input.reference').attr('lang', lang).attr('xml:lang', lang);
			$('#' + pane + ' div.content').attr('lang', lang).attr('xml:lang', lang);
			//$('#' + pane + ' div.versions-modal').toggle();
			$('#' + pane + ' a.version span.title').text($(this).attr('title'));
			$('#'+pane+' a.version').click();
		}
	});

	$('div.browse-modal div.book a').live('click', function(event) {
		event.preventDefault();

		var book_info = $(this).attr('class').replace(/selected| /gi, '').split('_');
		var book      = book_info[0];
		var chapters  = book_info[1];

		var browse_div = $(this).parents('div.browse-modal');

		var chapters_ul = browse_div.find('div.chapter ul');
		var html_f = '';

		// Clear out chapters ul
		chapters_ul.get(0).innerHTML = '';
		// Deselect previous
		browse_div.find('a.selected').removeClass('selected');

		for (i = 1; i <= chapters; i++)
		{
			html_f += '<li><a href="javascript:;">' + i + '</a></li>';
		}

		$(this).addClass('selected');
		chapters_ul.get(0).innerHTML = html_f;
	});

	$('div.browse-modal div.chapter a').live('click', function(event) {
		event.preventDefault();

		var pane = $(this).parent_pane();
		$('#' + pane + '_content').focus();
		var book = $('#' + pane + ' div.book a.selected').text();
		var chapter = $(this).text();

		$('#' + pane + ' input.reference').val(book + ' ' + chapter + ':1');
		$('#' + pane + ' div.chapter a.selected').removeClass('selected');
		$(this).addClass('selected');
		$('#' + pane + ' div.reference form').submit();

		//$('#' + pane + ' a.browse').removeClass('depressed');
		//$('#' + pane + ' div.browse-modal').hide();
		$('#'+pane+' a.browse').click();
	});

	// Remove default links from previous/next and bind click events
	$('div.reader a.prev_reader').click(function(event) {
		event.preventDefault();
		if (reader.paging === false) {
			reader.paging = true;
			var pane = $(this).parent_pane();
			var opposite_pane = pane.opposite_pane();
			$('#' + pane + '_content').unbind('scroll.hover'); // Prevent having to track too many things at once, it gets messy
			$('#' + opposite_pane + '_content').unbind('scroll.hover');
			
			$.each(reader[pane].loaded, function(key, val) {
				if (val === reader[pane].book + '.' + reader[pane].chapter) {
					if (reader[pane].verse > 1) {
						if (reader.parallel.enabled === true && reader.parallel.sync === true) {
							reader.scroll_to_reference(pane, reader[opposite_pane].book + '_' + reader[opposite_pane].chapter, false, false, 'paging');
						}
						reader.scroll_to_reference(pane, reader[pane].book + '_' + reader[pane].chapter, false, false, 'paging');
						return false;
					} else if ($.inArray(val, reader[pane].loaded) === 1 && reader[pane].previous !== '') {
						if (reader.parallel.enabled === true && reader.parallel.sync === true) {
							reader.chapters_load(reader[opposite_pane].previous, opposite_pane, true, false, false, reader[opposite_pane].loaded[0], 'paging');
						}
						reader.chapters_load(reader[pane].previous, pane, true, false, false, reader[pane].loaded[0], 'paging');
						return false;
					} else if ($.inArray(val, reader[pane].loaded) === 0) {
						if (reader.parallel.enabled === true && reader.parallel.sync === true) {
							reader.chapters_load(reader[opposite_pane].previous, pane, true, false, false, true, 'paging');
						}
						reader.chapters_load(reader[pane].previous, pane, true, false, false, true, 'paging');
						return false;
					} else {
						if (reader.parallel.enabled === true && reader.parallel.sync === true) {
							reader.scroll_to_reference(opposite_pane, reader[opposite_pane].loaded[key - 1], false, false, 'paging');
						}
						reader.scroll_to_reference(pane, reader[pane].loaded[key - 1], false, false, 'paging');
						return false;
					}
				}
			});
		}
	});
	// TODO: Make sure this works if you're in last chapter of Bible
	$('div.reader a.next_reader').click(function(event) {
		event.preventDefault();
		if (reader.paging === false) { // Only page if not already paging
			reader.paging = true;
			var pane = $(this).parent_pane();
			var opposite_pane = pane.opposite_pane();
			$('#' + pane + '_content').unbind('scroll.hover');
			$('#' + opposite_pane + '_content').unbind('scroll.hover');
			
			$.each(reader[pane].loaded, function(key, val) {
				if (val === reader[pane].book + '.' + reader[pane].chapter) {
					if (reader[pane].loaded.length === ($.inArray(val, reader[pane].loaded) + 1) && reader[pane].next !== '') {
						if (reader.parallel.enabled === true && reader.parallel.sync === true) {
							reader.chapters_load(reader[opposite_pane].next, opposite_pane, false, false, false, true, 'paging');
						}
						reader.chapters_load(reader[pane].next, pane, false, false, false, true, 'paging');
						return false;
					} else {
						if (reader.parallel.enabled === true && reader.parallel.sync === true) {
							reader.scroll_to_reference(opposite_pane, reader[opposite_pane].loaded[key + 1], false, false, 'paging');
						}
						reader.scroll_to_reference(pane, reader[pane].loaded[key + 1], false, false, 'paging');
						return false;
					}
				}
			});
		}
	});

	$('div.reader div.content span.trans, div.reader div.content span.study').tooltip({
		delay: 1000,
		showURL: false 
	});

	$('#main-search-form').unbind('submit');
	
	$('#main-search-form').submit(function(e) {
		var reference_original = e.target.q.value;
		var reference = reference_original.human_to_osis(reader.main.books.human_to_osis, '.');

		if (reference !== false) {
			e.preventDefault();
			$('#main input.reference').val(reference.osis_to_human());
			$('#main .reference form').submit();
		} else {
			// Continue on as normal
		}
	});

	user.init();
	reader.init();
	meta.init();

	// Hide loader, show reader
	$('#loading').hide();
	$('#wrapper').show();

	reader.post_init();
});

// Extend jQuery
(function($) {
	$.fn.parent_pane = function() {
		return $(this).parents('div.reader').attr('id');
	};
	$.fn.opposite_pane = function() {
		var pane = $(this).parents('div.reader').attr('id');
		pane.opposite_pane();
	};
})(jQuery);