
var Starboxes = {
  options: {
    buttons: 5,                                  // amount of clickable areas
    className : 'default',                       // default class
    color: false,                                // would overwrite the css style to set color on the stars
    duration: 0.6,                               // the duration of the revert effect, when effects are used
    effect: {
      mouseover: false,                          // use effects on mouseover, default false
      mouseout: (window.Effect && Effect.Morph)  // use effects on mouseout, default when available
    },
    hoverColor: false,                           // overwrites the css hover color
    hoverClass: 'hover',                         // the css hover class color
    ghostColor: false,                           // the color of the ghost stars, if used
    ghosting: false,                             // ghosts the previous vote
    identity: false,                             // a unique value you can give each starbox
    indicator: false,                            // use an indicator, default false
    inverse: false,                              // inverse the stars, right to left
    locked: false,                               // lock the starbox to prevent voting
    max: 5,                                      // the maximum rating of the starbox
    onRate: Prototype.emptyFunction,             // default onRate, function(element, memo) {}
    rated: false,                                // or a rating to indicate a vote has been cast
    ratedClass: 'rated',                         // class when rated
    rerate: false,                               // allow rerating
    overlay: 'default.png',                      // default star overlay image
    overlayImages: '../images/starbox/',         // directory of images relative to this file
    stars: 5,                                    // the amount of stars
    total: 0                                     // amount of votes cast
  }
};



Object.extend(
Starboxes, {
    REQUIRED_Prototype: "1.6.0.3",
    REQUIRED_Scriptaculous: "1.8.2",
    load: function () {
        this.require("Prototype");
        this.identify.counter = 1;
        if (/^(https?:\/\/|\/)/.test(this.options.overlayImages)) {
            this.imageSource = this.options.overlayImages;
        } else {
            var a = /starbox(?:-[\w\d.]+)?\.js(.*)/;
            this.imageSource = (($$("script[src]").find(function (b) {
                return b.src.match(a);
            }) || {}).src || "").replace(a, "") + this.options.overlayImages;
        }
    },
    require: function (a) {
        if (typeof window[a] == "undefined" || this.convertVersionString(window[a].Version) < this.convertVersionString(this["REQUIRED_" + a])) {
            throw "Starbox requires " + a + " >= " + this["REQUIRED_" + a];
        }
    },
    convertVersionString: function (a) {
        var b = a.replace(/_.*|\./g, "");
        b = parseInt(b + "0".times(4 - b.length));
        return a.indexOf("_") > -1 ? b - 1 : b;
    },
    fixIE: function (b) {
        var a = (new RegExp("MSIE ([\\d.]+)")).exec(b);
        return a ? parseFloat(a[1]) < 7 : false;
    } (navigator.userAgent),
    identify: function (b) {
        b = $(b);
        var c = b.readAttribute("id"),
        a = arguments.callee;
        if (c) {
            return c;
        }
        do {
            c = "starbox_" + a.counter++;
        } while ($(c));
        b.writeAttribute("id", c);
        return c;
    },
    imagecache: [],
    cacheImage: function (a) {
        if (!this.getCachedImage(a.src)) {
            this.imagecache.push(a);
        }
        return a;
    },
    getCachedImage: function (a) {
        return this.imagecache.find(function (b) {
            return b.src == a;
        });
    },
    buildQueue: [],
    queueBuild: function (a) {
        this.buildQueue.push(a);
    },
    processBuildQueue: function () {
        if (!this.buildQueue[0]) {
            this.batchLoading = true;
            return;
        }
        this.cacheBuildBatch(this.buildQueue[0]);
    },
    cacheBuildBatch: function (c) {
        var e = [],
        b = c.options.overlay,
        a = this.getCachedImage(b);
        this.buildQueue.each(function (f) {
            if (f.options.overlay == b) {
                e.push(f);
                this.buildQueue = this.buildQueue.without(f);
            }
        }.bind(this));
        if (!a) {
            var d = new Image;
            d.onload = function () {
                this.buildBatch(e, {
                    src: b,
                    height: d.height,
                    width: d.width,
                    fullsrc: d.src
                });
            }.bind(this);
            d.src = Starboxes.imageSource + b;
        } else {
            this.buildBatch(e, a);
        }
    },
    buildBatch: function (b, a) {
        b.each(function (c) {
            c.imageInfo = a;
            c.build();
        });
        this.processBuildQueue();
    },
    useEvent: function (a) {
        return {
            click: "click",
            mouseover: "mouseover",
            mouseout: a ? "mouseleave" : "mouseout"
        };
    } (Prototype.Browser.IE),
    capture: function (a) {
        if (!Prototype.Browser.IE) {
            a = a.wrap(function (e, d) {
                var c = Object.isElement(this) ? this : this.element,
                b = d.relatedTarget;
                if (b != c && !$A(c.select("*")).member(b)) {
                    e(d);
                }
            });
        }
        return a;
    }
});
Starboxes.load();
document.observe("dom:loaded", Starboxes.processBuildQueue.bind(Starboxes));
var Starbox = Class.create({
    initialize: function (a, b) {
        this.element = $(a);
        this.average = b;
        this.options = Object.extend(Object.clone(Starboxes.options), arguments[2] || {});
        $w("identity rated max total").each(function (c) {
            this[c] = this.options[c];
        }.bind(this));
        this.locked = this.options.locked || this.rated && !this.options.rerate;
        if (!this.identity) {
            this.identity = Starboxes.identify(this.element);
        }
        if (this.options.effect && (this.options.effect.mouseover || this.options.effect.mouseout)) {
            Starboxes.require("Scriptaculous");
        }
        Starboxes.queueBuild(this);
        if (Starboxes.batchLoading) {
            Starboxes.processBuildQueue();
        }
    },
    enable: function () {
        $w("mouseout mouseover click").each(function (c) {
            var b = c.capitalize(),
            a = this["on" + b].bindAsEventListener(this);
            this["on" + b + "_cached"] = c == "mouseout" && !Prototype.Browser.IE ? Starboxes.capture(a) : a;
            this.starbar.observe(Starboxes.useEvent[c], this["on" + b + "_cached"]);
        }.bind(this));
        this.buttons.invoke("setStyle", {
            cursor: "pointer"
        });
    },
    disable: function () {
        $w("mouseover mouseout click").each(function (a) {
            this.starbar.stopObserving(Starboxes.useEvent[a], this["on" + a.capitalize() + "_cached"]);
        }.bind(this));
        this.buttons.invoke("setStyle", {
            cursor: "auto"
        });
    },
    build: function () {
        this.starWidth = this.imageInfo.width;
        this.starHeight = this.imageInfo.height;
        this.starSrc = this.imageInfo.fullsrc;
        this.boxWidth = this.starWidth * this.options.stars;
        this.buttonWidth = this.boxWidth / this.options.buttons;
        this.buttonRating = this.options.max / this.options.buttons;
        if (this.options.effect) {
            this.zeroPosition = this.getBarPosition(0);
            this.maxPosition = this.getBarPosition(this.options.max);
        }
        var a = {
            absolute: {
                position: "absolute",
                top: 0,
                left: 0,
                width: this.boxWidth + "px",
                height: this.starHeight + "px"
            },
            base: {
                position: "relative",
                width: this.boxWidth + "px",
                height: this.starHeight + "px"
            },
            star: {
                position: "absolute",
                top: 0,
                left: 0,
                width: this.starWidth + "px",
                height: this.starHeight + "px"
            }
        };
        this.element.addClassName("starbox");
        this.container = (new Element("div", {
            className: this.options.className || ""
        })).setStyle({
            position: "relative"
        }).insert(this.status = (new Element("div")).insert(this.hover = (new Element("div")).insert(this.wrapper = (new Element("div", {
            className: "stars"
        })).setStyle(Object.extend({
            overflow: "hidden"
        },
        a.base)))));
        if (this.rated) {
            this.status.addClassName("rated");
        }
        if (this.locked) {
            this.status.addClassName("locked");
        }
        if (this.options.ghosting) {
            this.wrapper.insert(this.ghost = (new Element("div", {
                className: "ghost"
            })).setStyle(a.absolute));
            if (this.options.ghostColor) {
                this.ghost.setStyle({
                    background: this.options.ghostColor
                });
            }
            if (this.options.effect) {
                this.ghost.scope = this.ghost.identify();
            }
            this.setBarPosition(this.ghost, this.average, window.Effect && Effect.Morph);
        }
        this.wrapper.insert(this.colorbar = (new Element("div", {
            className: "colorbar"
        })).setStyle(a.absolute)).insert((new Element("div")).setStyle(a.absolute).insert(this.starbar = (new Element("div")).setStyle(a.base)));
        if (this.options.color) {
            this.colorbar.setStyle({
                background: this.options.color
            });
        }
        if (this.options.effect) {
            this.colorbar.scope = this.colorbar.identify();
        }
        this.options.stars.times(function (b) {
            var c;
            this.starbar.insert(c = (new Element("div")).setStyle(Object.extend({
                background: "url(" + this.starSrc + ") top left no-repeat",
                left: this.starWidth * b + "px"
            },
            a.star)));
            c.setStyle({
                left: this.starWidth * b + "px"
            });
            if (Starboxes.fixIE) {
                c.setStyle({
                    background: "none",
                    filter: "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + this.starSrc + "'', sizingMethod='scale')"
                });
            }
        }.bind(this));
        this.buttons = [];
        this.options.buttons.times(function (d) {
            var c, b = this.options.inverse ? this.boxWidth - this.buttonWidth * (d + 1) : this.buttonWidth * d;
            this.starbar.insert(c = (new Element("div")).setStyle({
                position: "absolute",
                top: 0,
                left: b + "px",
                width: this.buttonWidth + (Prototype.Browser.IE ? 1 : 0) + "px",
                height: this.starHeight + "px"
            }));
            c.rating = this.buttonRating * d + this.buttonRating;
            this.buttons.push(c);
        }.bind(this));
        this.setBarPosition(this.colorbar, this.average);
        this.element.update(this.container);
        this.inputs = {};
        $w("average max rated rerated total").each(function (b) {
            this.element.insert(this.inputs[b] = new Element("input", {
                type: "hidden",
                name: this.identity + "_" + b,
                value: "" + (b == "rerated" ? !!this[b] : this[b])
            }));
        }.bind(this));
        if (this.options.indicator) {
            this.hover.insert(this.indicator = new Element("div", {
                className: "indicator"
            }));
            this.updateIndicator();
        }
        if (!this.locked) {
            this.enable();
        }
    },
    updateAverage: function (a) {
        if (this.rated && this.options.rerate) {
            this.average = (this.total * this.average - this.rated) / (this.total - 1 || 1);
        }
        var b = this.rated ? this.total : this.total++;
        this.average = this.average == 0 ? a : (this.average * (this.rated ? b - 1 : b) + a) / (this.rated ? b : b + 1);
    },
    updateIndicator: function () {
        this.indicator.update((new Template(this.options.indicator)).evaluate({
            max: this.options.max,
            total: this.total,
            average: (this.average * 10).round() / 10
        }));
    },
    getBarPosition: function (b) {
        var a = this.boxWidth - b / this.buttonRating * this.buttonWidth;
        return parseInt(this.options.inverse ? a.ceil() : -1 * a.floor());
    },
    setBarPosition: function (a, b) {
        if (this.options.effect && this["activeEffect_" + a.scope]) {
            Effect.Queues.get(a.scope).remove(this["activeEffect_" + a.scope]);
        }
        var d = this.getBarPosition(b);
        if (arguments[2]) {
            var c = parseInt(a.getStyle("left")),
            f = this.getBarPosition(b);
            if (c == f) {
                return;
            }
            var e = ((this.maxPosition - (c - f).abs()).abs() / this.zeroPosition.abs()).toFixed(2);
            this["activeEffect_" + a.scope] = new(Effect.Morph)(a, {
                style: {
                    left: d + "px"
                },
                queue: {
                    position: "end",
                    limit: 1,
                    scope: a.scope
                },
                duration: this.options.duration * e
            });
        } else {
            a.setStyle({
                left: d + "px"
            });
        }
    },
    onClick: function (c) {
        var b = c.element();
        if (!b.rating) {
            return;
        }
        this.updateAverage(b.rating);
        if (this.options.indicator) {
            this.updateIndicator();
        }
        if (this.options.ghosting) {
            this.setBarPosition(this.ghost, this.average, window.Effect && Effect.Morph);
        }
        if (!this.rated) {
            this.status.addClassName("rated");
        }
        this.rerated = !!this.rated;
        this.rated = b.rating;
        if (!this.options.rerate) {
            this.disable();
            this.status.addClassName("locked");
            this.onMouseout(c);
        }
        var a = {};
        $w("average identity max rated rerated total").each(function (d) {
            if (d != "identity") {
                this.inputs[d].value = this[d];
            }
            a[d] = this[d];
        }.bind(this));
        this.options.onRate(this.element, a);
        this.element.fire("starbox:rated", a);
    },
    onMouseout: function (a) {
        this.setBarPosition(this.colorbar, this.average, this.options.effect && this.options.effect.mouseout);
        this.hovered = false;
        if (this.options.hoverClass) {
            this.hover.removeClassName(this.options.hoverClass);
        }
        if (this.options.hoverColor) {
            this.colorbar.setStyle({
                background: this.options.color
            });
        }
        this.element.fire("starbox:left");
    },
    onMouseover: function (b) {
        var a = b.element();
        if (!a.rating) {
            return;
        }
        this.setBarPosition(this.colorbar, a.rating, this.options.effect && this.options.effect.mouseover);
        if (!this.hovered && this.options.hoverClass) {
            this.hover.addClassName(this.options.hoverClass);
        }
        this.hovered = true;
        if (this.options.hoverColor) {
            this.colorbar.setStyle({
                background: this.options.hoverColor
            });
        }
        this.element.fire("starbox:changed", {
            identify: this.options.identity,
            max: this.options.max,
            rating: a.rating,
            total: this.total
        });
    }
});
