jQuery.fn.dropdown = function() {

   return this.each(function() {

      var $select = $(this);
      var $dropdown = $('<div class="select closed"></div>');
      var $dropdownInput = $('<input type="text" id="'+$select.attr('id')+'" value="" readonly="readonly" />');
      var $dropdownButton = $('<input type="button" value="&hellip;" />');
      var $dropdownOptionsContainer = $('<ul class="options"></ul>');
      var $dropdownOptions = $([]);

      var populateMenu = function() {
         $select.find('option').each(function(i) {
            var $dropdownOption = $('<li class="option_'+$(this).attr('value').replace(/\s+/g, '_')+'"><a href="#">'+$(this).text()+'</a></li>');
            if ($(this).is(':selected')) $dropdownOption.addClass('selected');
            $dropdownOptionsContainer.append($dropdownOption);
            $dropdownOption.find('a')
               .click(function() {
                  selectMenuOption(i);
                  hideMenuOptions();
                  return false;
               })
               .keydown(handleMenuOption)
               .keypress(function() {
                  return false;
               })
               .mousedown(function() {
                  return false;
               });
            $dropdownOptions = $dropdownOptions.add($dropdownOption);
         });
      }

      var showMenuOptions = function() {
         if ($dropdown.hasClass('closed')) setTimeout(function() {
            $dropdown.removeClass('closed');
            $dropdownOptionsContainer.show();
            $dropdown.addClass('opened').find('.selected a').focus();
         }, 10);
      }

      var hideMenuOptions = function() {
         $dropdownOptionsContainer.hide();
         $dropdown.removeClass('opened').addClass('closed');
         $dropdownInput.focus();
      }

      var selectMenuOption = function(i) {
         $select.val($select.find('option').eq(i).val()).trigger('change');
         $dropdownOptions.removeClass('selected').eq(i).addClass('selected');
         $dropdownInput.val($dropdownOptions.eq(i).text());
      }

      var handleMenuInput = function(e) {
         if (e.keyCode == 37 || e.keyCode == 38) {
            $dropdownOptions.filter('.selected').prev().find('a').click();
            return false;
         } else if (e.keyCode == 39 || e.keyCode == 40) {
            $dropdownOptions.filter('.selected').next().find('a').click();
            return false;
         } else {
            var matches = $dropdownOptions.filter(function() { return $(this).text().match(new RegExp('^'+String.fromCharCode(e.keyCode)+'\.*', 'i')); });
            if (matches.length) matches.eq((matches.index($('.selected'))+1) % (matches.length)).find('a').click();
         }
      }

      var handleMenuOption = function(e) {
         if (e.keyCode == 37 || e.keyCode == 38) {
            $(this).parent().prev().find('a').focus().click();
            return false;
         } else if (e.keyCode == 39 || e.keyCode == 40) {
            $(this).parent().next().find('a').focus().click();
            return false;
         } else if (e.keyCode == 13 || e.keyCode == 27) {
            hideMenuOptions(); return false;
         } else {
            var matches = $dropdownOptions.filter(function() { return $(this).text().match(RegExp('^'+String.fromCharCode(e.keyCode)+'\.*', 'i')); });
            if (matches.length) matches.eq((matches.index($('.selected'))+1) % (matches.length)).find('a').focus().click();
         }

      }

      var initMenu = function() {
         populateMenu();
         $select.hide().removeAttr('id').after($dropdown.append($dropdownInput.mousedown(showMenuOptions).keydown(handleMenuInput)).append($dropdownButton.mousedown(showMenuOptions)).append($dropdownOptionsContainer.hide()));
         selectMenuOption(Math.max($dropdownOptions.index($('.selected', $dropdownOptionsContainer)), 0));
         $(document).mousedown(function() { if ($dropdown.hasClass('opened')) hideMenuOptions(); });
      }

      initMenu();

   });

}
