/*	Claim.com behaviours
	Andrew Hedges, andrew@hedges.name
	2009-04-12
*/

$(function () {
	var duration, strlen, tmpls, setSelToVal, getLabelFromUl, showList, hideList;
	
	duration = 100; // duration (in milliseconds) of the list option animation
	strlen   = 17; // length of the select list labels on first run
	
	tmpls = {
		cont  : new Template('<div style="z-index: #{zidx};" class="faux-select">#{contents}</div>'),
		label : new Template('<a title="#{fulltext}">#{text}</a>'),
		opts  : new Template('<ul class="showing">#{opts}</ul>'),
		opt   : new Template('<li#{seld}#{style} data-selidx="#{selidx}"><a#{style} data-value="#{value}">#{text}</a></li>')
	};
	
	// set a select list to the given value
	setSelToVal = function (sel, val) {
		var i, idx;
		if ('undefined' === typeof sel.options) {
			sel = sel[0];
		}
		for (i = sel.options.length; i > 0; --i) {
			idx = i - 1;
			if (sel.options[idx].value === val) {
				sel.selectedIndex = idx;
				break;
			}
		}
	};
	// END: setSelToVal
	
	showList = function (ul, css) {
		// the setTimeout works around the case where the user clicks a select with the other already open
		setTimeout(function () {
			ul
				// keep the active state while the options are showing
				.next('a').addClass('selected').end()
				
				// slide the options to the visible state
				.animate(css.showing, duration, function () {
					// clicking a link should set a value, clicking anywhere should close the list
					$(document).mousedown(function (evt) {
						if ($(evt.target).parent().parent().parent('.faux-select').length > 0) {
							setListValue(evt.target);
						}
						hideList(ul, css);
						// rebuild the list in IE
						rebuildList(ul);
					});
				})
			;
		}, 10);
	};
	// END: showList
	
	hideList = function (ul, css) {
		ul.animate(css.hidden, duration, function (evt) {
			$(ul).next('a').removeClass('selected');
			$(document).unbind('mousedown');
		});
	};
	// END: hideList
	
	rebuildList = function (ul) {
		var sel, html;
		if (document.all && !window.opera) {
			// give time for the dust to settle before rebuilding the list
			setTimeout(function () {
				sel  = $(ul).parent('.faux-select').prev('select')[0];
				html = buildList(sel);
				$(ul).html(html);
			}, 100);
		}
	};
	// END: rebuildList
	
	buildHTML = function (sel) {
		var zidx, fulltext, text, opts, seld, html;
		
		zidx     = 10 * $(sel).attr('data-zindex'); // get the z-index for this group of elements
		fulltext = sel.options[sel.selectedIndex].text; // save selected text for later
		text     = truncate(fulltext, strlen);
		opts     = buildList(sel, text);
		
		// put the HTML together
		html = tmpls.cont.evaluate({
			zidx     : zidx,
			contents : tmpls.opts.evaluate({opts : opts}) + tmpls.label.evaluate({fulltext : fulltext, text : text})
		});
		
		return html;
	};
	// END: buildHTML
	
	buildList = function (sel, text) {
		var opts, fulltext, text, style;
		
		opts = '';
		
		if ('undefined' === typeof text) {
			fulltext = sel.options[sel.selectedIndex].text; // save selected text for later
			text     = truncate(fulltext, strlen);
		}
		
		// to capture "Please Select", change i = 1 to i = 0
		for (var i = 1, len = sel.options.length; i < len; ++i) {
			seld  = text === sel.options[i].text ? ' class="selected"' : '';
			style = 1 === i ? ' style="border-top: none;"' : '';
			opts += tmpls.opt.evaluate({
				seld   : seld,
				style  : style,
				selidx : i,
				value  : sel.options[i].value,
				text   : sel.options[i].text
			});
		}
		
		return opts;
	};
	// END: buildList
	
	setListValue = function (a) {
		var div, txt, trn, sel, val;
		
		if ('undefined' === typeof a.length) {
			a = $(a);
		}
		
		// set the label text
		div = a.parent().parent().parent('.faux-select');
		txt = a.html();
		trn = truncate(txt, strlen);
		div.children('a').html(trn).attr('title', txt);
		
		// set the select list value
		sel = div.prev('select');
		val = a.attr('data-value');
		setSelToVal(sel, val);
	};
	// END: setListValue
	
	// based very loosely on this: http://www.thetruetribe.com/javascript/30-javascript-design-patterns/44-truncating-text-with-javascript
	truncate = function (str, len) {
		var i;
		
		str = str || '';
		len = len || 17;
		
		if (str.length < len) return str;
		return str.substr(0, len) + '&#8230;';
	};
	// END: truncate
	
	$.each($('form.horizontal select,form.vertical select'), function () {
		var sel, html, ul, height, ptop, css;
		
		sel  = this; // save reference to the select list for use in our event handlers
		html = buildHTML(sel);
		
		// hide SELECT and append new HTML and attach events
		$(sel)
			.hide()
			.after(html)
		;
		
		// capture attributes we'll need for the animation
		ul     = $(sel).next().find('ul');
		height = ul.height() + 'px';
		ptop   = ul.css('padding-top');
		ul.removeClass('showing').show();
		
		css = {
			showing : {
				height        : height,
				paddingTop    : ptop
			},
			hidden  : {
				height        : 0,
				paddingTop    : 0
			}
		};
		
		// handle clicks on select options
		$('li a', ul)
			.live('mousedown', function () {
				setListValue($(this));
			})
		;
		
		// handle clicks on select label
		$(sel)
			.nextAll()
			.mousedown(function (evt) {
				0 === ul.height() ? showList(ul, css) : hideList(ul, css);
			})
		;
	});
	// END: $.each();
	
	strlen = 14; // change this so subsequent calls lop off more of the strings
	
	// replace submit buttons with input type=image buttons in IE6
	if (document.all && !window.opera && navigator.appVersion.indexOf('MSIE 6') > -1) {
		if ($('#homepage').length > 0) {
			$('label.submit').replaceWith('<input class="submit" type="image" src="assets/imgs/form-elements/submit-homepage.gif" alt="Submit Claim">');
		}
		else {
			$('label.submit').replaceWith('<input class="submit" type="image" src="assets/imgs/form-elements/submit.gif" alt="Submit Claim">');
		}
	}
});

//	Simple HTML templates in pure JavaScript, from: http://snipt.org/rpp
function Template(str) {
	this.rgx = /#\{([^{}]*)\}/g;
	this.str = str || '';
}
// END: Template constructor
 
Template.prototype.evaluate = function (vals) {
	var repr;
	vals = vals || {};
	repr = function (str, match) {
		return 'string' === typeof vals[match] || 'number' === typeof vals[match] ? vals[match] : str;
	};
	return this.str.replace(this.rgx, repr);
};
// END: Template.prototype.evaluate
