/**
 * Star Rating - jQuery plugin
 *
 * Copyright (c) 2006 Wil Stuckey
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 */

/**
 * Create a degradeable star rating interface out of a simple form structure.
 * Returns a modified jQuery object containing the new interface.
 *
 * @example jQuery('form.rating').rating();
 * @cat plugin
 * @type jQuery
 *
 */
(function($){ //create local scope
    /**
     * Takes the form element, builds the rating interface and attaches the proper events.
     * @param {Object} $obj
     */
    var buildRating = function($obj){
        var $obj = buildInterface($obj),
            $stars = $($obj.children('.star')),
            starCount = -1,
            $cancel = $($obj.children('.cancel')),
            $p = $($obj.children('p'));
        $obj.end();

        // hover events.
        // and focus events added
        $stars
            .mouseover(function(){
                event.drain();
                event.fill(this);
            })
            .mouseout(function(){
                event.drain();
                event.reset();
            })
            .focus(function(){
                event.drain();
                event.fill(this);
            })
            .blur(function(){
                event.drain();
                event.reset();
            });

        // cancel button events
        $cancel
            .mouseover(function(){
                event.drain();
            })
            .mouseout(function(){
                event.reset();
            })
            .focus(function(){
                event.drain();
            })
            .blur(function(){
                event.reset();
            });

        // click events.
        $cancel.click(function(){
            event.drain();
            starCount = 0;
            $(this).siblings('input')[0].value = this.value;
            $(this).addClass('on');
            return false;
        });
        $stars.click(function(){
            event.drain();
            event.fillon(this);
            starCount = $stars.index(this) + 1;
            $(this).siblings('input')[0].value = this.value;
            $p.html(this.text);
            return false;
        });

        var event = {
            fill: function(el){ // fill to the current mouse position.
                var index = $stars.index(el) + 1;
                $p.html(el.text);
                $stars.children('a').css('width', '100%').end()
                      .slice(0,index).addClass('hover').end();
            },
            fillon: function(el){ // fill to the current mouse position.
                var index = $stars.index(el) + 1;
                $stars.children('a').css('width', '100%').end()
                      .slice(0,index).addClass('on').end();
            },
            drain: function() { // drain all the stars.
                $p.html('');
                $stars.filter('.on').removeClass('on').end()
					  .filter('.hover').removeClass('hover').end();
                $cancel.removeClass('on');
            },
            reset: function(){ // Reset the stars to the default index.
                if (starCount == 0) {
                    $cancel.addClass('on');
                    $p.html('');
                } else if (starCount > 0) {
                    $stars.slice(0,starCount).addClass('on').end();
                    $p.html($stars.get(starCount - 1).text);
                }
            }
        }
        event.reset();
        return $obj;
    }


    /**
     * Accepts jQuery object containing a select element.
     * Returns the proper div structure for the star interface.
     *
     * @return jQuery
     * @param {Object} $select
     *
     */
    var buildInterface = function($select){
        var $container = $(document.createElement('div')).attr({
            "class": $select.attr('class')
        });
        var $optionGroup = $select.children('option');
        var size = $optionGroup.size() - 1;
        // Ignore the first element, which is the default (empty) selection.
        for (var i = 1, option; option = $optionGroup[i]; i++){
            if (i == size) {
                $div = $('<div class="cancel"><a href="#' + option.value + '">' + option.text + '</a></div>');
            } else {
                $div = $('<div class="star"><a href="#' + option.value + '" title="Bewerte ' + option.value + '/'+ size +' Punkten.">' + option.value + '</a></div>');
            }
            $div[0].selected = option.selected;
            $div[0].text = option.text;
            $div[0].value = option.value;
            $container.append($div[0]);
        }
        $div = $('<input name="' + $select.attr('name') +  '" type="hidden" value="" />');
        $container.append('<p></p>');
        $container.append($div[0]);
        $select.after($container).remove();

        return $container;
    }

    /**
     * Set up the plugin
     */
    $.fn.rating = function(){
        var stack = [];
        this.each(function(){
            var ret = [buildRating($(this))];
            stack = $.merge(ret, stack);
        });
        return $(stack);
    }

    $.fn.initRating = function() {
        this.each(function(){
            var $stars = $($(this).children('.star'));
            $stars.each(
               function() {
                   if(this.selected) {
                       $(this).click();
                   }
               }
            );
        });
        this.each(function(){
            var $stars = $($(this).children('.cancel'));
            $stars.each(
               function() {
                   if(this.selected) {
                       $(this).click();
                   }
               }
            );
        });
    }
    // fix ie6 background flicker problem.
	if ($.browser.msie == true) {
		document.execCommand('BackgroundImageCache', false, true);
	}
})(jQuery)