var MouseWatcher = new Class({
    
    Implements: [Options, Events], 

        options: {
            /*
            onStart: $empty,
            onEnd: $empty,
            onDrag: $empty,
            */
            downClass: 'down',
            dragClass: 'dragging'
        },

    isDragging: false,
    isDown: false,
    started: {x: false, y: false},
    finished: {x: false, y: false},

    initialize: function(element, options){
        this.setOptions(options);
        this.element = document.id(element);
        this.document = document.id(document);
        this.attachments = {
            mousedown: this.start.bind(this),
            mouseup: this.finish.bind(this)
        };
        this.boundMouseMove = this.mousemove.bind(this);
        this.attach();
    },
    
    attach: function(){
        this.element.addEvents(this.attachments);
        return this;
    },
    
    detach: function(){
        this.element.removeEvents(this.attachments);
        return this;
    },
    
    start: function(event){
        this.started = event.client;
        this.isDown = true;
        this.element.addClass(this.options.downClass);
        this.element.addEvent('mousemove', this.boundMouseMove);
        this.document.addEvent('mouseup', this.attachments.mouseup);
        this.fireEvent('start', this.started);
        return this;
    },
    
    finish: function(event){
        this.finished = (event) ? event.client : this.current;
        this.isDown = false;
        this.element.removeEvent('mousemove', this.boundMouseMove);
        this.document.removeEvent('mouseup', this.attachments.finish);
        this.element.removeClass(this.options.downClass);
        this.fireEvent('finish', this.finished);
        return this;
    },
    
    mousemove: function(event){
        this.current = event.client;
        this.isDragging = true;
        this.element.addClass(this.options.dragClass);
        this.fireEvent('drag', this.current);
        return this;
    }
    

});

var ThreeSixty = new Class({
    
    Extends: MouseWatcher,

        options: {
            totalFrames: 180,
            fileName: 'http://movies.apple.com/media/us/ipoditunes/nano/2009/qtvr/apple-ipod-nano-9up-us-20091218_880x425/ipodnano_9up_'
        },

    initialize: function(element, options){
        this.parent(element, options);
        this.img = this.element.getElement('img').addEvent('mousedown',function(event){
            event.preventDefault();
        });
        this.bound = this.drag.bind(this);
        this.addEvent('onDrag', this.bound);
        this.addEvent('onFinish', function(){
            this.current = this.next;
        }.bind(this))
        this.currentFrame = 1;
        this.loadImages();
    },
    
    drag: function(pos){
        next = this.currentFrame + (pos.x - this.started.x);
        if(next < 1){
            this.currentFrame = this.options.totalFrames;
        } else if(next > this.options.totalFrames) {
            this.currentFrame = 1;
        } else {
            this.currentFrame = next;
        }
        this.img.set('src', this.options.fileName + this.currentFrame.zeroPad(3) + '.jpg');
        this.started = pos;
        return this;
    },
    
    loadImages: function(attribute){
        (this.options.totalFrames - 1).times(function(num){
            new Element('img', { src: this.options.fileName + (num + 1).zeroPad(3) + '.jpg'});
        }, this);
        return this;
    },

});

Number.implement({
    zeroPad: function(length){
        var str = '' + this;
        while (str.length < length) {
            str = '0' + str;
        }
        return str;
    }
});

window.addEvent('domready', function(){
    new ThreeSixty('viewer',{
        totalFrames: 180,
        fileName: 'http://movies.apple.com/media/us/ipad/2010/spins/apple-ipad-us-20100127_512x512/ipad-1up-us-20100127_512x512_'
    });
});
<h1>ThreeSixty Viewer Demo by <a href="http://ryanflorence.com/mootools-threesixty-viewer-featuring-the-ipad/" target="_new">Ryan Florence</a></h1>
<h2>Click and drag</h2>
<div id="viewer">
    <img src="http://movies.apple.com/media/us/ipad/2010/spins/apple-ipad-us-20100127_512x512/ipad-1up-us-20100127_512x512_001.jpg" />
</div>
body {
    font-family: helvetica, arial;
    text-align: center;
}