// ----------------------------------------------------------------------------
// crossSelect - A jQuery Plugin to make multiple select boxes more intuitive
// v 0.5, requires jQuery 1.3.2 or later (may work with jQuery 1.3, but untested)
//
// Dual licensed under the MIT and GPL licenses.
// ----------------------------------------------------------------------------
// Copyright (C) 2009 Rhys Evans
// http://wheresrhys.co.uk/resources/
// ----------------------------------------------------------------------------
( function($) {
	$.fn.crossSelect = function(options) {
		var pars = $.extend( {}, jQuery.fn.crossSelect.defaults, options);
		var select, context, longestOpt, dimensions = new Array(), optionsList, chosenList, buttons;

		return this.each( function() {
			if ($(this).attr('multiple') === true) {
				select = $(this).hide().wrap('<div class="jqxs"></div>');
				context = $(select).parent();
				getLongestOpt();
				setDimensions();
				populateLists();
				createCrossSelecter();
				addListeners();
			}
		});

		function createCrossSelecter() {
			buttons = '<div class="jqxs_buttons">';
			if (!pars.clickSelects) {
				buttons += '<input type="button" value="'
						+ pars.select_txt
						+ '" class="jqxs_selectButton" disabled="disabled"></input><input type="button" value="'
						+ pars.remove_txt
						+ '" class="jqxs_removeButton" disabled="disabled"></input>';
			}
			buttons += '<input type="button" value="' + pars.selectAll_txt + '" class="jqxs_selectAllButton"';
			if ($('option:not([selected=true])', select).size() === 0) {
				buttons += ' disabled="disabled"';
			}
			buttons += '></input><input type="button" value="' + pars.removeAll_txt + '" class="jqxs_removeAllButton"';
			var test = $('option', select);
			if ($('option[selected=true]', select).size() === 0) {
				buttons += ' disabled="disabled"';
			}
			buttons += '></input></div>'
			$(context).append(optionsList + buttons + chosenList);
			$('ul', context).css( {
				height :dimensions['height'],
				width :dimensions['width']
			});
			if (pars.horizontal === 'hide') {
				$('ul', context).css( {
					'overflow-x' :'hidden'
				});
			}
		}

		function setDimensions() {
			switch (pars.vertical) {
			case 'expand':
				dimensions['height'] = $(select).children('option').size()
						* (pars.font * 1.25);
				break;
			case 'scroll':
				dimensions['height'] = (pars.font * 1.25) * pars.rows; // hack!!
				// dimensions['height'] = (pars.font *1.25) * Math.min($(select).children('option').size(),pars.rows);
				break;
			}
			switch (pars.horizontal) {
			case 'expand':
				dimensions['width'] = Math.max(longestOpt + 10, pars.listWidth);
				break;
			case 'scroll':
				dimensions['width'] = pars.listWidth;
				if (longestOpt > pars.listWidth) {
					dimensions['height'] = dimensions['height'] + 24;
				}
				break;
			case 'hide':
				dimensions['width'] = pars.listWidth; // remember to set
														// overflow-x hidden
				break;
			}
		}

		function populateLists() {
			var optOrder = 0;
			optionsList = '<ul class="jqxs_optionsList">';
			chosenList = '<ul class="jqxs_chosenList">';
			var newItem;
			$(select)
					.children('option')
					.each(
							function() {
								newItem = '';
								($(this).attr('selected') === true) ? newItem += '<li class="jqxs_selected"'
										: newItem += '<li';
								newItem += ' style="line-height: '
										+ (pars.font * 1.25) + 'px; height:'
										+ pars.font * 1.25 + 'px;font-size: '
										+ pars.font + 'px;width:' + longestOpt
										+ 'px">'
								newItem += $(this).text() + '<span>' + optOrder
										+ '</span></li>';
								optionsList += newItem;
								if ($(this).attr('selected') === true) {
									chosenList += newItem;
								}
								optOrder++;
							});
			chosenList += '</ul>';
			optionsList += '</ul>';
		}

		function getLongestOpt() {
			var text = "";
			$('option', select).each( function() {
				text += $(this).text() + "<br />";
			});
			$(context).append(
					'<span class="jqxs_ruler" style="font-size:' + pars.font
							+ 'px">' + text + '</span>');
			longestOpt = $('span', context).width() * 2; // hack!!
			$('span', context).remove();
		}

		function addListeners() {
			var thisSelect = select;
			var thisOptions = $('.jqxs_optionsList', context);
			var thisChosen = $('.jqxs_chosenList', context);
			var thisSelBut = $('.jqxs_selectButton', context);
			var thisRemBut = $('.jqxs_removeButton', context);
			var thisSelAllBut = $('.jqxs_selectAllButton', context);
			var thisRemAllBut = $('.jqxs_removeAllButton', context);
			if (pars.clickSelects) {
				$('li', thisOptions).click(selectNow);
				$('li', thisChosen).click(removeNow);
			} else {
				$('li', context).click(itemFocus);
				$(thisSelBut).click(selectMany);
				$(thisRemBut).click(removeMany);
			}
			if (pars.dblclick) {
				$('li', thisOptions).dblclick(selectNow);
				$('li', thisChosen).dblclick(removeNow);
			}
			$(thisSelAllBut).click(selectAll);
			$(thisRemAllBut).click(removeAll);

			function itemFocus() {
				if ($(this).hasClass('jqxs_focused')) {
					$(this).removeClass('jqxs_focused');
					if ($(this).parent().children('.jqxs_focused').length === 0) {
						disable(thisSelBut);
						disable(thisRemBut);
					}
					return;
				}
				if (!pars.clicksAccumulate) {
					$('li', thisOptions).removeClass('jqxs_focused');
					$('li', thisChosen).removeClass('jqxs_focused');
				} else {
					if ($(this).parent().hasClass('jqxs_optionsList')) {
						$('li', thisChosen).removeClass('jqxs_focused');
					} else {
						$('li', thisOptions).removeClass('jqxs_focused');
					}
				}
				$(this).addClass('jqxs_focused');
				if ($(this).parent().hasClass('jqxs_optionsList')) {
					enable(thisSelBut);
					disable(thisRemBut);
				} else {
					enable(thisRemBut);
					disable(thisSelBut);
				}
			}

			function selectOne() {
				var position = $('span', this).text();
				var option = $(thisSelect).children('option')[position];
				if ($(option).attr('selected') === false) {
					$(option).attr('selected', 'selected');
					$(this).removeClass('jqxs_focused');
					if (pars.clickSelects) {
						$(this).clone().appendTo(thisChosen).click(removeNow)
					} else {
						if (pars.dblclick) {
							$(this).clone().appendTo(thisChosen).click(
									itemFocus).dblclick(removeNow);
						} else {
							$(this).clone().appendTo(thisChosen).click(
									itemFocus);
						}
					}
					$(this).addClass('jqxs_selected');
				}
				document.forms[0].submit(); // hack!!
			}

			function removeOne() {
				var position = $('span', this).text();
				var option = $(thisSelect).children('option')[position];
				if ($(option).attr('selected') === true) {
					$(option).attr('selected', '');
					$($(thisOptions).children('li')[position]).removeClass(
							'jqxs_selected');
					$(this).remove();
				}
				document.forms[0].submit(); // hack!!
			}

			function selectNow() {
				$(this).each(selectOne);
				adjustButtons('sel');
			}

			function removeNow() {
				$(this).each(removeOne);
				adjustButtons('rem');
			}

			function selectMany() {
				$('.jqxs_focused', thisOptions).each(selectOne);
				adjustButtons('sel');
			}

			function removeMany() {
				$('.jqxs_focused', thisChosen).each(removeOne);
				adjustButtons('rem');
			}

			function selectAll() {
				$('li', thisOptions).each(selectOne);
				disable(thisRemBut);
				adjustButtons('sel');
				document.forms[0].submit(); // hack!!
			}

			function removeAll() {
				$('li', thisChosen).each(removeOne);
				disable(thisSelBut);
				adjustButtons('rem');
				document.forms[0].submit(); // hack!!
			}
			function adjustButtons(action) {
				switch (action) {
				case 'sel':
					disable(thisSelBut);
					enable(thisRemAllBut);
					if ($('li:not(.jqxs_selected)', thisOptions).size() === 0) {
						disable(thisSelAllBut);
					}
					break;
				case 'rem':
					disable(thisRemBut);
					enable(thisSelAllBut);
					if ($('li', thisChosen).size() === 0) {
						disable(thisRemAllBut);
					}
					break;
				}
			}
		}

		function enable(button) {
			$(button).addClass('jqxs_active').attr('disabled', '');
		}

		function disable(button) {
			$(button).removeClass('jqxs_active').attr('disabled', 'disabled');
		}
	};
})(jQuery);
jQuery.fn.crossSelect.defaults = {
	vertical :'scroll',
	horizontal :'hide',
	listWidth :300,
	font :13,
	rows :6,
	dblclick :true,
	clickSelects :false,
	clicksAccumulate :false,
	select_txt :'選択する',
	remove_txt :'削除する',
	selectAll_txt :'全て選択',
	removeAll_txt :'全て削除'
};
