
(function( $ ){
  $.fn.customSelect = function( options ) {
        
    var defaults = {
      id                  :   0,
      useLinks            :   false,
      optionsAlign        :   "joined",
      xOffset             :   0,
      yOffset             :   0
    };
  
    // merge default and user parameters  
    var options = $.extend( defaults, options);    
    
    // first locate all of the select tags on the page and hide them
    this.css('display','none');  
        
    //for each select on the page run this code
    this.each(function(i) {
      var $currentSelect = this;
      var uid = guid();
      
      createDivStructure($currentSelect, uid);
      bindEvents();
          
      //remove initialising class
      $(".initialising").removeClass("initialising");             
    });        
  
    //initially hide the drop down
    $('.select-options').hide();  
        
    function S4() {
      return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
    }
        
    function guid() {
      return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4());
    }
      
    function createDivStructure($currentSelect, uid){
      elementId = $($currentSelect).attr("id");
      
      //div container to hold the whole structure
      var selectWrapper = $("<div id='" + elementId + "' class='select-wrapper initialising'></div>");
      var selectContainer = $("<div id='select_" + uid + "' class='custom-select'></div>");
      
      //div container to hold the options
      var selectOptions = $("<div id='options_" + uid + "' class='select-options " + elementId + " ' style='position:absolute'></div>"); 
      var clearFloat = $("<div style='clear:both;'></div>");
      
      //insert the containers into the structure
      selectWrapper.insertAfter($currentSelect);
      selectContainer.appendTo(selectWrapper);
      selectOptions.appendTo('body');
      clearFloat.appendTo(selectContainer);
      
      var optionWidth = 0;
      
      //create the select options
      $("option", $currentSelect).each(function(i) {
        
        //get options text  
        var optionText = $(this).html();
        var optionLink = $(this).attr("data-link");
        if(!optionLink){
          optionLink = "#";
        }
        
        //create option replacement div
        var newOption = $("<div class='select-option'>" + optionText + "</div>");
        var noLink = newOption;
        
        if(options.useLinks){
          newOption = $("<div class='select-option'><a href='" + optionLink + "'>" + optionText + "</a></div>");
        }
          
        var selected = $(this).attr('selected');

        //if this option is the selected default 
        if(selected === true || selected == "selected") {
          //store it for later reference
          $selectedOption = noLink.attr("class", "selected");
                  
          //put it at the top of the select box
          $selectedOption.prependTo(selectContainer);
                            
          if(options.useLinks){
            newOption = $("<div class='select-option highlight'><a href='" + optionLink + "'>" + optionText + "</a></div>");
          } 
          else{
            newOption = $("<div class='select-option highlight'>" + optionText + "</div>");
          }                         
          
          newOption.clone().appendTo(selectOptions);
          optionWidth = $(this).parent().width();
        }
        
        //if it is not the selected default 
        else{        
          
          newOption.clone().appendTo(selectOptions);
          optionWidth = $(this).parent().width();
          //selectOptions.css("width", optionWidth);
        }           
      }); 
      
      alignDropDownLeft(uid);             
    }
    
    function alignDropDownTop(id){
      //Determine how to vertically align the drop down options
      
      selectId = "#select_" + id;
      selectWrapper = $(selectId).parents(".select-wrapper");             
      var distanceFromTop = selectWrapper.offset().top;
      var selectHeight = $(selectId).children(".selected").outerHeight();  
      optionstring = "#options_" + id;
      
      $(optionstring).css({"top" : distanceFromTop + selectHeight + options.yOffset});      
    }
    
    function alignDropDownLeft(id){
      //Determine how to horizontally align the drop down options
               
      //get width of option drop down
      var optionWidth = $("#options_" + id).outerWidth(true);     
      selectId = "#select_" + id;
      selectWrapper = $(selectId).parents(".select-wrapper");
            
      //get distance from the left of the page to the left side of select box
      var distanceFromLeft = $(selectId).offset().left;
                      
      //get distance from the right of the page to the right side of select box
      var distanceFromRight = $('body').width() - (distanceFromLeft + $(selectWrapper).width());
      
      optionstring = "#options_" + id;
      
      if(options.optionsAlign == "left"){
        $(optionstring).css({"left" : distanceFromLeft + options.xOffset, "text-align" : "left", "width" : $(selectId).width()});     
      }
      else if(options.optionsAlign == "right"){
        $(optionstring).css({"right" : distanceFromRight + options.xOffset, "text-align" : "right", "width" : $(selectId).width()});
      }
      else if(options.optionsAlign == "joined"){
        $(optionstring).css({"left" : distanceFromLeft + options.xOffset, "text-align" : "left", "width" : $(selectId).width()}); 
        //make the width of the dropdown the same width as the select
        $(optionstring).css({"width" : $(selectId).outerWidth(false) - 2});
      }       
    }   
    
    function bindEvents(){
      selectContainer = $(".initialising").children(".custom-select");
            
      //THIS WILL PROBABLY CAUSE PROBLEMS 
      $("html").click(function(){
        $('.select-options').stop().hide(10);   
        closeDropDown();  
      });
      
      /*if(options.closeOnMouseOut){
        
        $(".select-options").hover(function(){
          
        },
        function(){
          $(this).hide();
        });
      } */
                  
      //drop down click functionality           
      selectContainer.delegate(".selected", "click", function(event){
        //event.stopPropagation();  
        var container = $(this).parent();
        
        //refactor   
        //get the uid of this select-wrapper
        id = $(this).parents(".custom-select").attr("id");
        optionsId = id.split("_")[1];
            
        //create the string selector for the select-options
        optionstring = "#options_" + optionsId;
                
        $('.select-options').not($(optionstring)).stop().hide(10);        
        closeDropDown(); 
                      
        $(optionstring).toggle(10, function(){
          alignDropDownTop(optionsId);            
          //display the currently selected option again
          $(".select-option").removeClass("no-highlight");
                   
          if($(optionstring).is(":hidden")){
            //$(document).unbind('click');        
            closeDropDown();              
          }
          else{   
            //make its z-index higher    
            $(optionstring).css("z-index", 100);  
            
            //reset its borders
            $(container).css({
              "border-bottom-right-radius" : 0, 
              "border-bottom-left-radius" : 0, 
              "-webkit-border-bottom-left-radius" : 0, 
              "-webkit-border-bottom-right-radius" : 0, 
              "-moz-border-radius-bottomleft" : 0,
              "-moz-border-radius-bottomright" : 0
            });  
          }
        });    
        return false;
      });
                  
      //hovering over the selected option
      selectContainer.delegate(".selected", "hover", function(event){
        //refactor   
        //get the uid of this select-wrapper
        id = $(this).parents(".custom-select").attr("id");
        optionsId = id.split("_")[1];
            
        //create the string selector for the select-options
        optionstring = "#options_" + optionsId;       
                
        if($(optionstring + " .select-option").length > 0){         
          event.stopPropagation();
          $(this).css('cursor','pointer');  
            
          if(event.type === 'mouseenter'){
            $(this).addClass('selected-hover');
          }
          else{
            $(this).removeClass('selected-hover');  
          }     
        }           
      });      
        
      $('.select-options div.select-option').hover(
        function() {          
          $newHighlightedOption = $(this);
          var container = $newHighlightedOption.parent(".select-options");   
          
          $highlightedOption = $(".highlight", container);
          
          if($newHighlightedOption.get(0) == $highlightedOption.get(0)){
            //dont highlight the currently selected option
            $($highlightedOption).removeClass("no-highlight");         
          }
          else{
            $($highlightedOption).addClass("no-highlight");   
            $newHighlightedOption.addClass("roll-over");    
          }               
        },
        function() {
          $(this).removeClass("roll-over");
        }
      );
      
      $('.select-options div').click(function(event){      
        event.stopPropagation();     
        closeDropDown();
             
        $clickedOption = $(this);      
        id = $(this).parent().attr("id");
        optionid = id.split("_")[1];
            
        var optionContainer = $("#options_" + optionid);    
        var selectContainer = $("#select_" + optionid);
                       
        $(".highlight", optionContainer).removeClass("highlight");
        $($clickedOption).addClass("highlight");    
        
        $selectedOption = $(".selected", selectContainer);
        $($selectedOption).replaceWith( "<div class='selected'>" + $($clickedOption).html() + "</div>" );
                
        //get the index of the new selected option
        var optionIndex = $('.select-option', optionContainer).index($clickedOption);
        
        //update the real select box    
        $(selectContainer).parent().prev("select").first().get(0).selectedIndex = optionIndex;
        $(optionContainer).hide(10);
        $(selectContainer).parent().prev("select").closest("form").submit();
        
      });         
            
    }
  
    function closeDropDown(){
      $(".custom-select").removeAttr("style");
    }
  
  };
})( jQuery );

