/*

TO DO: Test in all browsers, clean up theme file, prepare documentation, minisite?

Uniform v1.5
Copyright © 2009 Josh Pyles / Pixelmatrix Design LLC
http://pixelmatrixdesign.com

Requires jQuery 1.3 or newer

Much thanks to Thomas Reynolds and Buck Wilson for their help and advice on this

Disabling text selection is made possible by Mathias Bynens <http://mathiasbynens.be/>
and his noSelect plugin. <http://github.com/mathiasbynens/noSelect-jQuery-Plugin>

Also, thanks to David Kaneda and Eugene Bond for their contributions to the plugin

License:
MIT License - http://www.opensource.org/licenses/mit-license.php

Usage:

$juf(function(){
  $juf("select, :radio, :checkbox").uniform();
});

You can customize the classes that Uniform uses:

$juf("select, :radio, :checkbox").uniform({
  selectClass: 'mySelectClass',
  radioClass: 'myRadioClass',
  checkboxClass: 'myCheckboxClass',
  checkedClass: 'myCheckedClass',
  focusClass: 'myFocusClass'
});

Enjoy!

*/
$juf = jQuery.noConflict();

(function($juf) {
  $juf.uniform = {
    options: {
      selectClass:   'selector',
      radioClass: 'radio',
      checkboxClass: 'checker',
      fileClass: 'uploader',
      filenameClass: 'filename',
      fileBtnClass: 'action',
      fileDefaultText: 'No file selected',
      fileBtnText: 'Choose File',
      checkedClass: 'checked',
      focusClass: 'focus',
      disabledClass: 'disabled',
      activeClass: 'active',
      hoverClass: 'hover',
      useID: true,
      idPrefix: 'uniform',
      resetSelector: false
    },
    elements: []
  };

  if($juf.browser.msie && $juf.browser.version < 7){
    $juf.support.selectOpacity = false;
  }else{
    $juf.support.selectOpacity = true;
  }

  $juf.fn.uniform = function(options) {

    options = $juf.extend($juf.uniform.options, options);

    var el = this;
    //code for specifying a reset button
    if(options.resetSelector != false){
      $juf(options.resetSelector).mouseup(function(){
        function resetThis(){
          $juf.uniform.update(el);
        }
        setTimeout(resetThis, 10);
      });
    }

    function doSelect(elem){

      var divTag = $juf('<div />'),
          spanTag = $juf('<span />');

      divTag.addClass(options.selectClass);

      if(options.useID){
        divTag.attr("id", options.idPrefix+"-"+elem.attr("id"));
      }
      
      var selected = elem.find(":selected:first");
      if(selected.length == 0){
        selected = elem.find("option:first");
      }
      spanTag.html(selected.text());
      
      elem.css('opacity', 0);
      elem.wrap(divTag);
      elem.before(spanTag);

      //redefine variables
      divTag = elem.parent("div");
      spanTag = elem.siblings("span");

      elem.change(function() {
        spanTag.text(elem.find(":selected").text());
        divTag.removeClass(options.activeClass);
      })
      .focus(function() {
        divTag.addClass(options.focusClass);
      })
      .blur(function() {
        divTag.removeClass(options.focusClass);
        divTag.removeClass(options.activeClass);
      })
      .mousedown(function() {
        divTag.addClass(options.activeClass);
      })
      .mouseup(function() {
        divTag.removeClass(options.activeClass);
      })
      .click(function(){
        divTag.removeClass(options.activeClass);
      })
      .hover(function() {
        divTag.addClass(options.hoverClass);
      }, function() {
        divTag.removeClass(options.hoverClass);
      })
      .keyup(function(){
        spanTag.text(elem.find(":selected").text());
      });

      //handle disabled state
      if($juf(elem).attr("disabled")){
        //box is checked by default, check our box
        divTag.addClass(options.disabledClass);
      }
      $juf.uniform.noSelect(spanTag);
      
      storeElement(elem);

    }

    function doCheckbox(elem){

      var divTag = $juf('<div />'),
          spanTag = $juf('<span />');

      divTag.addClass(options.checkboxClass);

      //assign the id of the element
      if(options.useID){
        divTag.attr("id", options.idPrefix+"-"+elem.attr("id"));
      }

      //wrap with the proper elements
      $juf(elem).wrap(divTag);
      $juf(elem).wrap(spanTag);

      //redefine variables
      spanTag = elem.parent();
      divTag = spanTag.parent();

      //hide normal input and add focus classes
      $juf(elem)
      .css("opacity", 0)
      .focus(function(){

        divTag.addClass(options.focusClass);
      })
      .blur(function(){

        divTag.removeClass(options.focusClass);
      })
      .click(function(){

        if(!$juf(elem).attr("checked")){
          //box was just unchecked, uncheck span
          spanTag.removeClass(options.checkedClass);
        }else{
          //box was just checked, check span.
          spanTag.addClass(options.checkedClass);
        }
      })
      .mousedown(function() {
        divTag.addClass(options.activeClass);
      })
      .mouseup(function() {
        divTag.removeClass(options.activeClass);
      })
      .hover(function() {
        divTag.addClass(options.hoverClass);
      }, function() {
        divTag.removeClass(options.hoverClass);
      });

      //handle defaults
      if($juf(elem).attr("checked")){
        //box is checked by default, check our box
        spanTag.addClass(options.checkedClass);
      }

      //handle disabled state
      if($juf(elem).attr("disabled")){
        //box is checked by default, check our box
        divTag.addClass(options.disabledClass);
      }

      storeElement(elem);

    }

    function doRadio(elem){

      var divTag = $juf('<div />'),
          spanTag = $juf('<span />');

      divTag.addClass(options.radioClass);

      if(options.useID){
        divTag.attr("id", options.idPrefix+"-"+elem.attr("id"));
      }

      //wrap with the proper elements
      $juf(elem).wrap(divTag);
      $juf(elem).wrap(spanTag);

      //redefine variables
      spanTag = elem.parent();
      divTag = spanTag.parent();

      //hide normal input and add focus classes
      $juf(elem)
      .css("opacity", 0)
      .focus(function(){
        divTag.addClass(options.focusClass);
      })
      .blur(function(){
        divTag.removeClass(options.focusClass);
      })
      .click(function(){
        if(!$juf(elem).attr("checked")){
          //box was just unchecked, uncheck span
          spanTag.removeClass(options.checkedClass);
        }else{
          //box was just checked, check span
          $juf("."+options.radioClass + " span."+options.checkedClass + ":has([name='" + $juf(elem).attr('name') + "'])").removeClass(options.checkedClass);
          spanTag.addClass(options.checkedClass);
        }
      })
      .mousedown(function() {
        if(!$juf(elem).is(":disabled")){
          divTag.addClass(options.activeClass);
        }
      })
      .mouseup(function() {
        divTag.removeClass(options.activeClass);
      })
      .hover(function() {
        divTag.addClass(options.hoverClass);
      }, function() {
        divTag.removeClass(options.hoverClass);
      });

      //handle defaults
      if($juf(elem).attr("checked")){
        //box is checked by default, check span
        spanTag.addClass(options.checkedClass);
      }
      //handle disabled state
      if($juf(elem).attr("disabled")){
        //box is checked by default, check our box
        divTag.addClass(options.disabledClass);
      }

      storeElement(elem);

    }

    function doFile(elem){
      //sanitize input
      $jufel = $juf(elem);

      var divTag = $juf('<div />'),
          filenameTag = $juf('<span>'+options.fileDefaultText+'</span>'),
          btnTag = $juf('<span>'+options.fileBtnText+'</span>');

      divTag.addClass(options.fileClass);
      filenameTag.addClass(options.filenameClass);
      btnTag.addClass(options.fileBtnClass);

      if(options.useID){
        divTag.attr("id", options.idPrefix+"-"+$jufel.attr("id"));
      }

      //wrap with the proper elements
      $jufel.wrap(divTag);
      $jufel.after(btnTag);
      $jufel.after(filenameTag);

      //redefine variables
      divTag = $jufel.closest("div");
      filenameTag = $jufel.siblings("."+options.filenameClass);
      btnTag = $jufel.siblings("."+options.fileBtnClass);

      //set the size
      if(!$jufel.attr("size")){
        var divWidth = divTag.width();
        //$jufel.css("width", divWidth);
        $jufel.attr("size", divWidth/10);
      }

      //actions
      $jufel
      .css("opacity", 0)
      .focus(function(){
        divTag.addClass(options.focusClass);
      })
      .blur(function(){
        divTag.removeClass(options.focusClass);
      })
      .change(function(){
        var filename = $juf(this).val();
        filename = filename.split(/[\/\\]+/);
        filename = filename[(filename.length-1)];
        filenameTag.text(filename);
      })
      .mousedown(function() {
        if(!$juf(elem).is(":disabled")){
          divTag.addClass(options.activeClass);
        }
      })
      .mouseup(function() {
        divTag.removeClass(options.activeClass);
      })
      .hover(function() {
        divTag.addClass(options.hoverClass);
      }, function() {
        divTag.removeClass(options.hoverClass);
      });

      //handle defaults
      if($jufel.attr("disabled")){
        //box is checked by default, check our box
        divTag.addClass(options.disabledClass);
      }
      
      $juf.uniform.noSelect(filenameTag);
      $juf.uniform.noSelect(btnTag);
      storeElement(elem);

    }

    function storeElement(elem){
      //store this element in our global array
      elem = $juf(elem).get();
      if(elem.length > 1){
        $juf.each(elem, function(i, val){
          $juf.uniform.elements.push(val);
        });
      }else{
        $juf.uniform.elements.push(elem);
      }
    }
    
    //noSelect v1.0
    $juf.uniform.noSelect = function(elem) {
      function f() {
       return false;
      };
      $juf(elem).each(function() {
       this.onselectstart = this.ondragstart = f; // Webkit & IE
       $juf(this)
        .mousedown(f) // Webkit & Opera
        .css({ MozUserSelect: 'none' }); // Firefox
      });
     };

    $juf.uniform.update = function(elem){
      if(elem == undefined){
        elem = $juf($juf.uniform.elements);
      }
      //sanitize input
      elem = $juf(elem);

      elem.each(function(){
        //do to each item in the selector
        //function to reset all classes
        $jufe = $juf(this);

        if($jufe.is("select")){
          //element is a select
          spanTag = $jufe.siblings("span");
          divTag = $jufe.parent("div");

          divTag.removeClass(options.hoverClass+" "+options.focusClass+" "+options.activeClass);

          //reset current selected text
          spanTag.html($jufe.find(":selected").text());

          if($jufe.is(":disabled")){
            divTag.addClass(options.disabledClass);
          }else{
            divTag.removeClass(options.disabledClass);
          }

        }else if($jufe.is(":checkbox")){
          //element is a checkbox
          spanTag = $jufe.closest("span");
          divTag = $jufe.closest("div");

          divTag.removeClass(options.hoverClass+" "+options.focusClass+" "+options.activeClass);
          spanTag.removeClass(options.checkedClass);

          if($jufe.is(":checked")){
            spanTag.addClass(options.checkedClass);
          }
          if($jufe.is(":disabled")){
            divTag.addClass(options.disabledClass);
          }else{
            divTag.removeClass(options.disabledClass);
          }

        }else if($jufe.is(":radio")){
          //element is a radio
          spanTag = $jufe.closest("span");
          divTag = $jufe.closest("div");

          divTag.removeClass(options.hoverClass+" "+options.focusClass+" "+options.activeClass);
          spanTag.removeClass(options.checkedClass);

          if($jufe.is(":checked")){
            spanTag.addClass(options.checkedClass);
          }

          if($jufe.is(":disabled")){
            divTag.addClass(options.disabledClass);
          }else{
            divTag.removeClass(options.disabledClass);
          }
        }else if($jufe.is(":file")){
          divTag = $jufe.parent("div");
          filenameTag = $jufe.siblings(options.filenameClass);
          btnTag = $jufe.siblings(options.fileBtnClass);

          divTag.removeClass(options.hoverClass+" "+options.focusClass+" "+options.activeClass);

          filenameTag.text($jufe.val());

          if($jufe.is(":disabled")){
            divTag.addClass(options.disabledClass);
          }else{
            divTag.removeClass(options.disabledClass);
          }
        }
      });
    }

    return this.each(function() {
      if($juf.support.selectOpacity){
        var elem = $juf(this);

        if(elem.is("select")){
          //element is a select
          if(elem.attr("multiple") != true){
            //element is not a multi-select
            doSelect(elem);
          }
        }else if(elem.is(":checkbox")){
          //element is a checkbox
          doCheckbox(elem);
        }else if(elem.is(":radio")){
          //element is a radio
          doRadio(elem);
        }else if(elem.is(":file")){
          //element is a file upload
          doFile(elem);
        }

      }
    });
  };
})(jQuery);

