(function($) {
  $.multiselect = { version: '0.1' };
  $.fn.multiselect = function(options) {
    $.multiselect = $.extend({
      defaultMessage: '',
      multiple: null,
      color: '#000',
      background_color: '#fff',
      hover_color: '#fff',
      hover_background_color: '#7f9db9'
    }, options || {});
    return $(this).map(create_select);
  };

  function create_select() {
    var select = $(this), select_width, t_width, multiple, options, ns, menu, selected, text, menu_item;
    select_width = select.width();
    if (select.get(0).tagName.toLowerCase() != 'select') throw 'object was not select element.';
    if ($.multiselect.multiple == null) multiple = (select.attr('multiple'));
    selected = select.find(':selected');
    options = select.find('option');
    if (select.attr('name') == null || select.attr('name').length == 0) throw 'name attribute must be present.';

    ns = $('<div></div>').attr('name', select.attr('name')).attr('class', select.attr('class')).attr('id', select.attr('id')).html('<div class="multiselect_button"></div><input type="text" class="multiselect_default" id="__multiselect_'+select.attr('name')+'_text" readonly="readonly" />').addClass('multiselect_select');
    text = ns.find('input:text');
    if (multiple) {
      if (selected.length == 0) text.attr('value', $.multiselect.defaultMessage);
      else text.attr('value', $.map(selected, function(n) { return $(n).text(); }).join(', '));
    } else {
      if (selected.length == 0) {
        text.attr('value', options.eq(0).text());
        selected.push(options.eq(0));
      } else {
        text.attr('value', selected.eq(0).text());
      }
    }
    select.replaceWith(ns);
    t_width = select_width - ns.find('.multiselect_button').width() - 2;
    // if ($.browser.msie) t_width--;  // adjust size for ie
    ns.find('input:text').width(t_width);
    ns.find('span').eq(0).css('padding-top', Math.floor((select.height() - 16)/2)).css('cursor', 'pointer');

    menu = $('<div></div>').attr('id', '__multiselect_'+select.attr('name')).width(ns.width()).addClass('multiselect_menu').appendTo(document.body);
    if (multiple) menu.addClass('multiselect_multiple');
    menu.click(none);
    options.each(function(i, v) {
      menu_item = $('<div></div>').html('<input type="checkbox" name="'+select.attr('name')+((multiple) ? '[]' : '')+'" value="'+v.value+'"'+(this.selected ? ' checked="checked"' : '')+' />'+v.innerHTML).addClass('multiselect_menuitem').appendTo(menu);
      if (this.selected) menu_item.addClass('multiselect_menuitem_selected');
    });
    if (multiple) menu.find('input:checkbox').mouseup(menu_mouseup);
    else menu.find('input:checkbox').css('display', 'none');
    menu.find('.multiselect_menuitem').hover(menu_mouseover, menu_mouseout)
      .click(menu_click);
    ns.click(none);
    ns.mousedown(ns_mousedown);
    return ns.get(0);
  }

  function none(e) {
    e.preventDefault();return false;
  }
  function ns_mousedown(e) {
    e.preventDefault();
    $(this).multiselect_toggle();
    return false;
  }
  function menu_mouseup(e) {
    var self = $(this);
    e.preventDefault();
    (self.is(':checked')) ? self.removeAttr('checked') : self.attr('checked', 'checked');
    return false;
  }
  function menu_mouseover(e) {
    $(this).css('background-color', $.multiselect.hover_background_color).css('color', $.multiselect.hover_color);
  }
  function menu_mouseout(e) {
    if (!$(this).hasClass('multiselect_menuitem_selected')) $(this).css('background-color', $.multiselect.background_color).css('color', $.multiselect.color);
  }
  function menu_click(e) {
    e.preventDefault();
    var parent = $(this).parent(), text = $('#'+parent.attr('id')+'_text');
    var cb = $(this).find('input:checkbox');
    if (parent.hasClass('multiselect_multiple')) {
      if (cb.is(':checked')) {
        cb.removeAttr('checked');
        $(this).removeClass('multiselect_menuitem_selected').css('background-color', $.multiselect.background_color).css('color', $.multiselect.color);
      } else {
        cb.attr('checked', 'checked');
        $(this).addClass('multiselect_menuitem_selected').css('background-color', $.multiselect.hover_background_color).css('color', $.multiselect.hover_color);
      }
      var values = parent.find('.multiselect_menuitem_selected'), v;
      if (values.length == 0) v = $.multiselect.defaultMessage;
      else v = values.map(function(){return $(this).text(); }).get().join(', ');
      text.attr('value', v).parent().trigger('change');
      return false;
    } else {
      parent.find('input:checkbox').removeAttr('checked');
      cb.attr('checked', 'checked');
      text.attr('value', $(this).text());
      parent.find('.multiselect_menuitem_selected')
        .removeClass('multiselect_menuitem_selected')
          .css('background-color', '#fff');
      $(this).addClass('multiselect_menuitem_selected');
      text.parent().multiselect_toggle();
      text.parent().trigger('change');
      return true;
    }
  }

  $.fn.multiselect_hide = function() {
    $(this).each(function(e) {
      var self = $('#__multiselect_'+$(this).attr('name'));
      if (self.is(':visible')) self.slideUp('fast');
    });
  };

  $.fn.multiselect_show = function() {
    $(this).each(function(e) {
      var self = $('#__multiselect_'+$(this).attr('name'));
      if (!self.is(':visible')) {
        var dim = $(this).offset();
        self.css({top:(dim.top+$(this).height())+'px', left:dim.left+'px'}).slideDown('fast');
      }
    });
  };

  $.fn.multiselect_toggle = function() {
    $('.multiselect_menu').each(function() {if ($(this) != self && $(this).is(':visible')) $(this).slideUp('fast');});
    $(this).each(function(e) {
      var self = $('#__multiselect_'+$(this).attr('name'));
      if (self.is(':visible')) self.slideUp('fast');
      else {
        var dim = $(this).offset();
        self.css({top:(dim.top+$(this).height())+'px', left:dim.left+'px'}).slideDown('fast');
      }
    });
  };

  $.fn.multiselect_selected = function() {
    var self = $(this).eq(0);
    var menu = $('#__multiselect_' + self.attr('name'));
    return menu.find('input:checked').map(function() { return { name: this.name, value:this.value }; });
  };
})(jQuery);

/*jQuery(window).bind('scroll', function(e){
  if (jQuery('.multiselect_menu').is(':visible'))
    jQuery('.multiselect_menu').hide();
});*/

jQuery(document).click(function(e){if (jQuery('.multiselect_menu').is(':visible')) jQuery('.multiselect_menu').slideUp('fast');});
