// class:           ImageScrOOler
// version:         1.62
// dependencies:    mootools 1.2.x
// tested on:       FireFox 3, IE7, Safari 4 (beta), Opera 9.60
// last updated:    10/09/2009 15:57:01
// url:             http://fragged.org/
// author:          dimitar chrostoff <christoff@gmail.com>
// authorised use:  modify and use as you deem fit. any link back appreciated :)

var ImageScrOOler = new Class({
    Implements: [Options, Events],
    moveDirection: "right",
    moveOffset: 0,
    options: {
        // set defaults here
        targetElement: $empty,  // you NEED the target element to be an object
        imagePath: "",          // prefix images with this
        imageSpacing: 10,       // margin between scrolling images
        imageOpacity: .8,
        clickEvent: function(clickObj) {
            window.location.href = escape(clickObj.url);
        },     // this can open a url or call
        moveDelay: 16,          // animation delay between frames, in ms
        moveSteps: 1,           // move by number of pixels
        imageHeight: 70,        // default image height
        showProgress: true,     // show a 'status' like layer
        defaultMessage: 'Click on the images below',
        showMessage: ' Show me items from ',
        imageClass: 'cur',      // css class to apply to each image, for example, with cursor: pointer
        EOL: 1000,              // delay after eaching END-OF-LINE in ms
        carousel: !true         // if true, it just recycles images and no EOL is reached, works left to right.
    },
    initialize: function(data, options) {
        // data needs to be an array of JSON like this:
        // var data = [
        //    {image: 'Blowfish.gif', url: '/Blowfish', title: 'Blowfish'},
        //    {image: 'Bronx.gif', url: '/Bronx', title: 'Bronx'} ...
        // ];

        this.setOptions(options);

        if ($type(this.options.targetElement) != "element")
            return false;

        if (!data.length)
            return false;

        this.data = data;
        this.options.targetElement.empty();

        // setup our elements
        if (this.options.showProgress) // progress / mouseover status element, style #moostats via css
            this.stats = new Element("span", { id: 'moostats', html: "Initialising..." }).inject(this.options.targetElement);

        // containing titles layer
        this.container = new Element("div", {
            styles: {
                overflow: "hidden",
                height: this.options.imageHeight,
                visibility: "hidden",
                width: this.options.targetElement.getSize().x,
                float: "left"
            }
        }).inject(this.options.targetElement);

        this.subcontainer = new Element("div", {
            styles: {
                overflow: "hidden",
                height: this.options.imageHeight,
                visibility: "hidden",
                width: this.options.targetElement.getSize().x,
                "white-space": "nowrap"
            }
        }).inject(this.container);

        // load images and start moving.
        this.loadAssets();

        // prepare containers and make visible
        this.container.setStyles({
            visibility: "visible",
            opacity: 0.1
        }).fade(0, 1);

        this.subcontainer.addEvents({
            mouseleave: function() {
                this.move();
            } .bind(this),
            mouseenter: function() {
                this.stop();
            } .bind(this)
        }).setStyle("visibility", "visible");

        if (this.options.showProgress)
            this.stats.set("html", this.options.defaultMessage);
        // get going!
        this.stop(); // clear up reload issues
        this.subcontainer.scrollTo(0, 0);
        this.move();
    },
    loadAssets: function() {
        // injects images into our containers.
        var _this = this; // can't bind this for the images onload so save a ref.

        this.subcontainer.empty();
        // loop array
        this.data.each(function(el, i) {
            new Asset.image(_this.options.imagePath + el.image, {
                title: el.title,
                "class": "mOOimage",
                onload: function() {
                    if (i < _this.data.length)
                        this.setStyle("margin-right", _this.options.imageSpacing);

                    // add css settings to images here or change / force height.
                    this.set({
                        styles: {
                            height: _this.options.imageHeight
                        },
                        opacity: _this.options.imageOpacity
                    }).addClass(_this.options.imageClass).inject(_this.subcontainer);

                    _this.addImageEvents(this, el);
                }
            });

            if (_this.options.showProgress) {
                // output how many loaded
                if (i < _this.data.length)
                    _this.stats.set("html", i + ' loaded...');
            }
        }); // each

        this.subcontainer.scrollTo(0, 0);
    },
    addImageEvents: function(img, el) {
        return img.set({
            events: {
                click: function() {
                    if (this.options.clickEvent != null) {
                        // collect some garbage
                        this.stop();
                        img.removeEvents();
                        this.options.clickEvent.run(el);
                    }
                } .bind(this),
                mouseenter: function() {
                    if (this.options.showProgress && img.get("title") != null)
                        this.stats.set("html", " <span style='color:#666'>" + img.get("title") + "</span>");
                    img.set("opacity", 1);
                } .bind(this),
                mouseleave: function() {
                    if (this.options.showProgress)
                        this.stats.set("html", this.options.defaultMessage);
                    img.set("opacity", this.options.imageOpacity);
                } .bind(this)
            }
        });
    },
    getSize: function() {
        // based on mootools 1.11 getSize, gets the subcontainer size and scroll data
        this.subSize = {
            'scroll': { 'x': this.subcontainer.scrollLeft, 'y': this.subcontainer.scrollTop },
            'size': { 'x': this.subcontainer.offsetWidth, 'y': this.subcontainer.offsetHeight },
            'scrollSize': { 'x': this.subcontainer.scrollWidth, 'y': this.subcontainer.scrollHeight }
        };
    },
    frame: function() {
        // move one frame in whatever direction and handle stop/turn around.
        if (this.moveDirection == "right") {
            this.getSize();
            this.subcontainer.scrollTo(this.subSize.scroll.x + this.options.moveSteps, 0); // number of pixels

            // carousel -- works left to right only.
            if (this.options.carousel) {
                var first = this.subcontainer.getElements("img.mOOimage")[0];

                if (first) {
                    var firstWidth = first.getStyle("width").toInt() + this.options.imageSpacing;
                    if (this.subSize.scroll.x >= firstWidth + this.moveOffset) {
                        this.moveOffset += firstWidth;
                        var current;
                        this.data.each(function(el, i) {
                            if (first.href) {
                                if (first.href.indexOf(el.image) >= 0) {
                                    current = el;
                                    return;
                                } 
                            }
                        });
                        this.addImageEvents(first.clone(), current).inject(this.subcontainer); // moves to end.
                        first.removeEvents().removeClass("mOOimage").setOpacity(0.1);
                    }

                }
                return false;
            }

            this.getSize();
            if (this.subSize.size.x + this.subSize.scroll.x >= this.subSize.scrollSize.x && this.subSize.scroll.x > 0) {
                // reached end of data to right, go left
                this.stop();
                this.fireEvent("complete", this.moveDirection);
                this.moveDirection = "left";

                (function() {
                    this.move();
                }).delay(this.options.EOL, this); // pause at end of line to allow seeing last item
            }


        }
        else {
            this.getSize();
            this.subcontainer.scrollTo(this.subSize.scroll.x - this.options.moveSteps, 0); // move nn pixels

            this.getSize();
            if (this.subSize.scroll.x <= 0) {
                // reached left end of data to left, turn around...
                this.stop();
                this.fireEvent("complete", this.moveDirection);
                this.moveDirection = "right";

                (function() {
                    this.move();
                }).delay(this.options.EOL, this); // pause at end of line to allow seeing last item
            };
        }
    },
    move: function() {
        // drives moving
        this.stop();
        this.moveTimer = (function() {
            this.frame();
        }).periodical(this.options.moveDelay, this);
    },
    stop: function() {
        // stop moving.
        $clear(this.moveTimer);
    },
    turn: function() {
        // swap direction
        this.moveDirection = (this.moveDirection == "right") ? "left" : "right";
        this.subcontainer.getElements("img").filter(function(el) {
            return !el.hasClass("mOOimage"); // remove ghost images
        }).dispose();
    }
});   // end ImageScrOOler class


