/*
 * Alternate Select Multiple (asmSelect) 1.0.4a beta - jQuery Plugin
 * http://www.ryancramer.com/projects/asmselect/
 *
 * Copyright (c) 2008 by Ryan Cramer - http://www.ryancramer.com
 *
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * Realty_V2 edition
 */
(function($) {

 $.fn.asmSelect = function(customOptions) {

 var options = {
 prefix: '',

 listType: 'ol', // Ordered list 'ol', or unordered list 'ul'
 sortable: false, // Should the list be sortable?
 highlight: false, // Use the highlight feature?
 animate: false, // Animate the the adding/removing of items in the list?
 addItemTarget: 'bottom', // Where to place new selected items in list: top or bottom
 hideWhenAdded: false, // Hide the option when added to the list? works only in FF
 debugMode: false, // Debug mode keeps original select visible
 listAlign: 'bottom',
 removeLabel: 'remove', // Text used in the "remove" link
 highlightAddedLabel: 'Added: ', // Text that precedes highlight of added item
 highlightRemovedLabel: 'Removed: ', // Text that precedes highlight of removed item

 containerClass: 'asmContainer', // Class for container that wraps this widget
 selectClass: 'asmSelect', // Class for the newly created <select>
 optionDisabledClass: 'asmOptionDisabled', // Class for items that are already selected / disabled
 listClass: 'asmList', // Class for the list ($ol)
 listSortableClass: 'asmListSortable', // Another class given to the list when it is sortable
 listItemClass: 'asmListItem', // Class for the <li> list items
 listItemLabelClass: 'asmListItemLabel', // Class for the label text that appears in list items
 removeClass: 'asmListItemRemove', // Class given to the "remove" link
 highlightClass: 'asmHighlight' // Class given to the highlight <span>

 };

 $.extend(options, customOptions);


 return this.each(function(index) {

 var $original = $(this); // the original select multiple
 var $container; // a container that is wrapped around our widget
 var $select; // the new select we have created
 var $ol; // the list that we are manipulating
 var buildingSelect = false; // is the new select being constructed right now?
 var ieClick = false; // in IE, has a click event occurred? ignore if not

 function init() {

 // initialize the alternate select multiple

 $select = $("<select></select>")
 .addClass(options.selectClass)
 .attr('id', options.prefix + options.selectClass + index);

 $selectRemoved = $("<select></select>");

 $ol = $("<" + options.listType + "></" + options.listType + ">")
 .addClass(options.listClass)
 .attr('id', options.prefix + options.listClass + index);

 $container = $("<div></div>")
 .addClass(options.containerClass)
 .attr('id', options.prefix + options.containerClass + index);

 buildSelect();

 $select.change(selectChangeEvent)
 .click(selectClickEvent);

 if ( options.listAlign == 'top' )
 $original.change(originalChangeEvent)
 .wrap($container).before($ol).before($select);
 else
 $original.change(originalChangeEvent)
.wrap($container).before($select).before($ol);

 if(options.sortable) makeSortable();

 //if($.browser.msie) $ol.css('display', 'inline-block');
 }

 function makeSortable() {

 // make any items in the selected list sortable
 // requires jQuery UI sortables, draggables, droppables

 $ol.sortable({
 items: 'li.' + options.listItemClass,
 handle: '.' + options.listItemLabelClass,
 axis: 'y',
 update: function() {
 $(this).children("li").each(function(n) {
 if($(this).is(".ui-sortable-helper")) return;
 $option = $('#' + $(this).attr('rel'));
 $original.append($option);
 });
 }
 }).addClass(options.listSortableClass);
}

 function selectChangeEvent() {

 // an item has been selected on the regular select we created
 // check to make sure it's not an IE screwup, and add it to the list

 if($.browser.msie && $.browser.version < 7 && !ieClick) return;
 var id = $(this).children("option:selected").slice(0,1).attr('rel');
 addListItem(id);
 ieClick = false;
 }

 function selectClickEvent() {

 // IE6 lets you scroll around in a select without it being pulled down
 // making sure a click preceded the change() event reduces the chance
 // if unintended items being added. there may be a better solution?

 ieClick = true;
 }

 function originalChangeEvent(e) {

 // select or option change event manually triggered
 // on the original <select multiple>, so rebuild ours

 $select.empty();
 $ol.empty();
 buildSelect();

 // opera has an issue where it needs a force redraw, otherwise
 // the items won't appear until something else forces a redraw
 if($.browser.opera) $ol.hide().fadeIn("fast");
 }

 function buildSelect() {

 // build or rebuild the new select that the user
 // will select items from
 buildingSelect = true;

 // add a first option to be the home option / default selectLabel
 $select.prepend("<option>" + $original.attr('title') + "</option>");

 $original.children("option").each(function(n) {

 var $t = $(this);
 var id;


 if(!$t.attr('id')) $t.attr('id', options.prefix + 'asm' + index + 'option' + n);
 id = $t.attr('id');

 if($t.is(":selected")) {
 addListItem(id);
 addSelectOption(id, true);
 } else {
 addSelectOption(id);
 }
 });

 if(!options.debugMode) $original.hide(); // IE6 requires this on every buildSelect()
 selectFirstItem();
 buildingSelect = false;
 }

 function addSelectOption(optionId, disabled) {

 // add an <option> to the <select>
 // used only by buildSelect()

 if(disabled == undefined) var disabled = false;

 var $O = $('#' + optionId);
 var $option = $("<option>" + $O.text() + "</option>")
 .val($O.val())
 .attr('rel', optionId);

 if(disabled) disableSelectOption($option);

 $select.append($option);
 }

 function selectFirstItem() {
 // select the firm item from the regular select that we created
 $select.children(":eq(0)").attr("selected", true);
 }

 function disableSelectOption($option) {

 // make an option disabled, indicating that it's already been selected
 // because safari is the only browser that makes disabled items look 'disabled'
 // we apply a class that reproduces the disabled look in other browsers

 $option.addClass(options.optionDisabledClass)
 .attr("selected", false)
 .attr("disabled", true);

 if(options.hideWhenAdded) $option.hide();
 //if($.browser.msie) $select.hide().show(); // this forces IE to update display
 }

 function enableSelectOption($option) {

 // given an already disabled select option, enable it

 $option.removeClass(options.optionDisabledClass)
 .attr("disabled", false);

 if(options.hideWhenAdded) $option.show();
 //if($.browser.msie) $select.hide().show(); // this forces IE to update display
 }

 function addListItem(optionId) {

 // add a new item to the html list

 var $O = $('#' + optionId);

 if(!$O) return; // this is the first item, selectLabel

 var $removeLink = $("<a></a>")
.attr("href", "#")
.addClass(options.removeClass)
 .prepend(options.removeLabel)
.click(function() {
 dropListItem($(this).parent('li').attr('rel'));
 return false;
 });

 var $itemLabel = $("<span></span>")
 .addClass(options.listItemLabelClass)
 .html($O.html());

 var $item = $("<li></li>")
 .attr('rel', optionId)
 .addClass(options.listItemClass)
 .append($itemLabel)
 .append($removeLink)
 .hide();

 if(!buildingSelect) {
 if($O.is(":selected")) return; // already have it
 $O.attr('selected', true);
 }

 if(options.addItemTarget == 'top' && !buildingSelect) {
 $ol.prepend($item);
 if(options.sortable) $original.prepend($O);
 } else {
 $ol.append($item);
 if(options.sortable) $original.append($O);
 }

 addListItemShow($item);

 disableSelectOption($("[rel=" + optionId + "]", $select));

 if(!buildingSelect) {
 setHighlight($item, options.highlightAddedLabel);
 selectFirstItem();
 if(options.sortable) $ol.sortable("refresh");
 }

 }

 function addListItemShow($item) {
 // reveal the currently hidden item with optional animation
 // used only by addListItem()

 if(options.animate && !buildingSelect) {
 $item.animate({
 opacity: "show",
 height: "show"
 }, 100, "swing", function() {
 $item.animate({
 height: "+=2px"
 }, 50, "swing", function() {
 $item.animate({
 height: "-=2px"
 }, 25, "swing");
 });
 });
 } else {
 $item.show();
 }
 }

 function dropListItem(optionId, highlightItem) {

 // remove an item from the html list

 if(highlightItem == undefined) var highlightItem = true;
 var $O = $('#' + optionId);

 $O.attr('selected', false);
 $item = $ol.children("li[rel=" + optionId + "]");

 dropListItemHide($item);
 enableSelectOption($("[rel=" + optionId + "]", options.removeWhenAdded ? $selectRemoved : $select));

 if(highlightItem) setHighlight($item, options.highlightRemovedLabel);

 }

 function dropListItemHide($item) {
 // remove the currently visible item with optional animation
 // used only by dropListItem()

 if(options.animate && !buildingSelect) {

 $prevItem = $item.prev("li");

 $item.animate({
 opacity: "hide",
 height: "hide"
 }, 100, "linear", function() {
 $prevItem.animate({
 height: "-=2px"
 }, 50, "swing", function() {
 $prevItem.animate({
 height: "+=2px"
 }, 100, "swing");
 });
 $item.remove();
 });

 } else {
 $item.remove();
 }
 }

 function setHighlight($item, label) {

 // set the contents of the highlight area that appears
 // directly after the <select> single
 // fade it in quickly, then fade it out

 if(!options.highlight) return;

 $select.next("#" + options.highlightClass + index).remove();

 var $highlight = $("<span></span>")
 .hide()
 .addClass(options.highlightClass)
 .attr('id', options.prefix + options.highlightClass + index)
 .html(label + $item.children("." + options.listItemLabelClass).slice(0,1).text());

 $select.after($highlight);

 $highlight.fadeIn("fast", function() {
 setTimeout(function() { $highlight.fadeOut("slow"); }, 50);
 });
 }

 init();
 });
 };

})(jQuery); 
