//
// jTouchControl, a jQuery plug-in for various iPhone-style controls
//
// License: MIT License
// History:
//  Oct-2009 Create by Satoshi Nakajima
//
(function($) {
  $.fn.jTControl = function(type, options) {
    var fn = activator[type];
    return fn ? this.each(function() { activator[type].call($(this), options) }) : this;
  };
  
  // Private functions
  var activator = {
    progressBar: function(options) {
        //this.html("<div></div>");
        var $t = this;              // for faster access from private functions
        var self = this.get(0);     // ditto
        var child = document.createElement("div");
        self.appendChild(child);
        var $c = $(child);   // ditto
        self.setValue = function(val, animated) {
            var w = Math.floor(val*$t.width()) + 'px';
            var t = (animated > 0) ? ('width ' + animated + 's') : '';
            $c.css({ '-webkit-Transition':t, 'width': w } );
        };
        self.setValue(0);
    },
    
    slider: function(options) {
        // Private variables (closure variablable)
        var defaults = {
            'padding' : 0,
            'thumb' : null,         // thumb selector expression
            'steps' : null          // number of steps (null = continuous)
        };
        var options = $.extend(defaults, options);  
        var $t = this;              // for faster access
        var self = this.get(0);     // ditto
        var $c = $t.children(options.thumb).css({ 'position':'relative', 'visibility':'visible' });  
        var _value = 0;             // accessible via set/getValue
        var dragging = false;
        var width = $t.width() - options.padding*2;

        self.setValue = function(val, animated, notify) {
            _value = Math.min(Math.max(val,0), 1.0);
            if (options.steps && !dragging) { _value = Math.round(_value * options.steps) / options.steps; }
            $c.css({    '-webkit-Transition': (animated > 0) ? ('left ' + animated + 's') : '', 
                        'left': options.padding-$c.width()/2 + Math.floor(_value*width) + "px", 
                        'top': Math.floor(($t.height()-$c.height())/2) + "px" });
            if (notify) { $t.trigger("valuechanged"); }
        };
        
        self.getValue = function() { return _value; };
        
        var onMouseDown = function(e) {
            // Closure variable (valid during a single dragging operation)
            var fTouch;         // yes: touch device (such as iPhone)
            
            var onMouseMove = function(e) {
                e.preventDefault();
                var clientX = fTouch ? e.touches[0].clientX : e.clientX;
                self.setValue((clientX - self.offsetLeft) / $t.width(), 0, false);
            };
            var onMouseUp = function(e) {
                e.preventDefault();
                dragging = false;
                self.setValue(self.getValue(), 0.2, true);    // For notification and steps
                
                $c.removeClass("dragging");
                if (fTouch) {
                    self.removeEventListener("touchmove", onMouseMove, false);  
                    self.removeEventListener("touchend", onMouseUp, false); 
                    self.removeEventListener("touchcancel", onMouseUp, false); 
                } else {
                    $(document).unbind("mousemove", onMouseMove);
                    $(document).unbind("mouseup", onMouseUp);
                }
            };
            
            e.preventDefault();
            dragging = true;
            fTouch = e.touches ? true:false;
            var clientX = fTouch ? e.touches[0].clientX : e.clientX;
            self.setValue((clientX - self.offsetLeft) / $t.width(), 0.2, false);
            
            $c.addClass("dragging");
            if (fTouch) {
                self.addEventListener("touchmove", onMouseMove, false);  
                self.addEventListener("touchend", onMouseUp, false);  
                self.addEventListener("touchcancel", onMouseUp, false);  
            } else {
                $(document).bind("mousemove", onMouseMove);
                $(document).bind("mouseup", onMouseUp);
            }
        };

        // Initialize the control 
        this.append($c);        
        self.setValue(0);
        this.bind("mousedown", onMouseDown);
        if (self.addEventListener) {
            self.addEventListener("touchstart", onMouseDown, false);  
        }
    }
  };
})(jQuery);
