/* 
 This file was generated by Dashcode and is covered by the 
 license.txt included in the project.  You may edit this file, 
 however it is recommended to first turn off the Dashcode 
 code generator otherwise the changes will be lost.
 */

if (!window.dashcode) {
    dashcode = new Object();
}

// To listen for focus events so we can "blur" on our touch events
if( window.Touch ){
	window.addEventListener("focus", function(event){	
                            if( event.target.id )
                            dashcode.TouchButtonEventHandler.focusedElement = event.target;
                            }, true);
}
//
// CreateTouchButtonEventHandler(element, actionCallback, highlightCallback)
// An object to handle touch events like a button.  If touch events are not available, will fallback to standard mouse down events.
//
// element: element to attach the event handler
// actionCallback: action to call when the button is "pressed"
// highlightCallback: action to call when the button should be "highlighted"
//
// Note: Properties and methods beginning with underbar ("_") are considered private and subject to change in future Dashcode releases.

// Public properties:
//     element: The element attached to this handler (read-only)
//	  eventsEnabled: boolean representing if events should be ignored

//     actionCallback: action to call when the element is "pressed" (event causing the press is passed to the callback)
//	  highlightCallback: action to call when element should be "highlighted" (boolean is passed to the highlight function to specify if the element should highlight ornot)
//		
// Public Methods:
//	  setActionCallback: set function to call when the element's action should be performed
//		example:	
//			handler.setActionCallback( function(event){ alert("Button Pressed"); } );
//	  setHighlightCallback: set function to call when the element should highlight
//		example:
//			handler.setActionCallback(	function(highlight){
//														if( highlight )
//															myElement.style.backgroundColor = "blue";
//														else
//															myElement.style.backgroundColor = "";
//													} );

dashcode.CreateTouchButtonEventHandler = function(element,actionCallback,highlightCallback,swipeCallback)
{
    return new dashcode.TouchButtonEventHandler(element,actionCallback,highlightCallback);
}

dashcode.TouchButtonEventHandler = function(element, actionCallback, highlightCallback, swipeCallback) 
{
	if( !element ){
		return false;
	}
	
	this.element = element;
	this.actionCallback = actionCallback;
	this.highlightCallback = highlightCallback;
	this.swipeCallback = swipeCallback;
	this.eventsEnabled = true;
	this.cancelOnDrag = true;
    
	// For JavaScript event handlers
	var self = this;
	
	this._inside = false;
	this._highlighted = false;
	this._useTouchEvents = (undefined != window.Touch);
	
	if( !this._useTouchEvents ){
		this._mousedownHandler = function(event) { self._mousedown(event); }
		this._mousemoveHandler = function(event)
		{
			event.stopPropagation();
			event.preventDefault();
		}
		this._mouseoverHandler = function(event) { self._mouseover(event); }
		this._mouseoutHandler = function(event) { self._mouseout(event); }
		this._mouseupHandler = function(event) { self._mouseup(event); }
	}
    
	if( this._useTouchEvents ){
		this.element.addEventListener('touchstart', function(event) { self._touchStart(event); }, false);
		this.element.addEventListener('touchend', function(event) { self._touchEnd(event); }, false);
		this.element.addEventListener('touchmove', function(event) { self._touchMove(event); }, false);
		this.element.addEventListener('touchcancel', function(event) { self._touchCancelled(event); } , false);
        // Turn off the highlight & Callout (popup bubble)
        element.style.webkitTapHighlightColor = "rgba(0,0,0,0)";
        element.style.webkitTouchCallout = "none";        
	}else{
		this.element.addEventListener("mousedown", self._mousedownHandler, false);
	}    
}

dashcode.TouchButtonEventHandler.prototype.setActionCallback = function(actionCallback)
{
	this.actionCallback = actionCallback;
}

dashcode.TouchButtonEventHandler.prototype.setHighlightCallback = function(highlightCallback)
{
	this.highlightCallback = highlightCallback;
}

dashcode.TouchButtonEventHandler._eventsDisableCount = 0;

dashcode.TouchButtonEventHandler.__defineSetter__("disableEvents", function(disable){
                                                  dashcode.TouchButtonEventHandler._eventsDisableCount += disable?1:-1;
                                                  
                                                  if( dashcode.TouchButtonEventHandler._eventsDisableCount < 0 ){
                                                  dashcode.TouchButtonEventHandler._eventsDisableCount = 0;
                                                  console.error("dashcode.TouchButtonEventHandler.disableEvents must have matched true and false values");
                                                  }
                                                  });

dashcode.TouchButtonEventHandler.__defineGetter__("disableEvents", function(){
                                                  return (dashcode.TouchButtonEventHandler._eventsDisableCount > 0 );
                                                  });


dashcode.TouchButtonEventHandler.prototype._touchStart = function(event)
{
	var self = this;
    
	// If touch is disabled and we are not in the middle of touch detection for this button
	// then we ignore
	if( dashcode.TouchButtonEventHandler.disableEvents && !this._timeoutTimer)
		return false;
    
	// There are some cases where these elements steal the event when placed as a child of this.element.
	if( (event.srcElement.tagName == "INPUT" || event.srcElement.tagName == "TEXTAREA" || event.srcElement.tagName == "SELECT") 
       && event.srcElement != this.element )
		return false;
    
	if( !this.eventsEnabled || !this.actionCallback )
		return false;
	
	event.stopPropagation();
	self._inTouchEvent = true;
    
	self._startX = event.targetTouches[0].clientX;
	self._startY = event.targetTouches[0].clientY;
    
	if( this._timeoutTimer ){
		clearTimeout(this._timeoutTimer);
		delete this._timeoutTimer;
	}else{
		dashcode.TouchButtonEventHandler.disableEvents = true;
		this._timeoutTimer = setTimeout(function(){ self._touchTimeout(event,false) },100);
	}
}

dashcode.TouchButtonEventHandler.prototype._touchTimeout = function(event,docompletion)
{
	var self = this;
	
	delete this._timeoutTimer;
    
	this._highlight(true);
	
	this._inside = true;	
    
	if( docompletion )
		setTimeout(function(){ self._touchComplete(event,true); }, 150);
}

dashcode.TouchButtonEventHandler.prototype._touchMove = function(event)
{
	// Don't track motion when multiple touches are down in this element (that's a gesture)
	if (event.targetTouches.length != 1 || !this._inTouchEvent){
		// If we used move for one of our 
		if( this._blockTouchEvents )
			event.preventDefault();
        
		return false;
	}
    
	var x = event.targetTouches[0].clientX;
	var y = event.targetTouches[0].clientY;
    var touchInElement = dashcode.pointInElement(x,y,this.element);
	
	if( this.swipeCallback && 
       (Math.abs(this._startX - x) > 5) ){
		if( this.swipeCallback(event,this.element,this._startX - x) ){
			event.preventDefault();
			event.stopPropagation();
			this._touchComplete(event,false);	
			this._blockTouchEvents = true;
			return true;				
		}
	}
    
	if( this._timeoutTimer && (Math.abs(this._startY - y) > 5)){
		// If we have a swipe callback and we haven't hit the threshold, then 
		this._touchComplete(event,false);	
		return false;
	}
    
	// If the cancel on drag bit is set, we cancel
	// the touch event if there is ANY x/y movement after 
	// touchstart.
	if( this.cancelOnDrag &&
       ((Math.abs(this._startX - x) > 5) ||
		(Math.abs(this._startY - y) > 5)) ){
		this._touchComplete(event,false);	
		return false;	
	}
    
	event.preventDefault();
	event.stopPropagation();
    
	if( !this.cancelOnDrag ){
		if( touchInElement && this._touchDownOutsideOfElement){
			this._inside = true;
			this._highlight(true);
			event.preventDefault();
			delete this._touchDownOutsideOfElement;
		}else if( !touchInElement && this._inside ){
			this._touchDownOutsideOfElement = true;
			this._inside = false;
			this._highlight(false);
		}
	}
}

dashcode.TouchButtonEventHandler.prototype._touchEnd = function(event)
{
	var self = this;
	
	if( !this._inTouchEvent )
		return false;
    
	// Prevent the browser from doing its default thing (scroll, zoom)
	event.preventDefault();
    
	if (!this._timeoutTimer) {
        // We need to make sure there is time to draw the highlight
        setTimeout(function(){ self._touchComplete(event,true); },0);
	} else {
		// In order to not fire on a zoom gesture (double click), if we get the touchend
		// before our original timer fired, we need to wait again to see if there will 
		// be another touch event or not (if not, then we do or normal click handling).
		clearTimeout(this._timeoutTimer);
		this._timeoutTimer = setTimeout(function(){ self._touchTimeout(event,true) },100);
	}
	
	this._inTouchEvent = false;
	
	return true;
}

dashcode.TouchButtonEventHandler.prototype._touchCancelled = function(event)
{	
	if( !this._inTouchEvent )
		return false;
    
	if( this._timeoutTimer )
		clearTimeout(this._timeoutTimer);
    
	this._touchComplete(event,false);
    
	return true;
}

dashcode.TouchButtonEventHandler.prototype._callActionCallback = function()
{
    var self = this;
    
    self._savedOnclick = null;
    if (this.element.onclick) {
        self._savedOnclick = this.element.onclick;
    }
    
    this.element.onclick = function(event) {
        self.actionCallback(event);
        self.element.onclick = self._savedOnclick;
        delete self._savedOnclick;
    }
    var clickEvent = document.createEvent("MouseEvents");
    clickEvent.initMouseEvent("click",false,false,window,1,0,0,0,0,false,false,false,false,0,null);
    this.element.dispatchEvent(clickEvent);
}

dashcode.TouchButtonEventHandler.prototype._touchComplete = function(event,performAction)
{
	this._highlight(false);
	this._inTouchEvent = false;
    
	if( this._timeoutTimer ){
		clearTimeout(this._timeoutTimer);
		delete this._timeoutTimer;
	}
	
	// Perform callback if we're inside the button
	try {
		if (this._inside && performAction && this.actionCallback != null) {
			// Make sure any focused element is no longer focused (remove keyboard)
			if( dashcode.TouchButtonEventHandler.focusedElement ) {
				dashcode.TouchButtonEventHandler.focusedElement.blur();
            }
            
            this._callActionCallback();
		}
	} catch(ex) {
		throw ex;
	} finally {
		delete this._inside;
	}	
	
	dashcode.TouchButtonEventHandler.disableEvents = false;
}

dashcode.TouchButtonEventHandler.prototype._highlight = function(highlight)
{
	if( this._highlighted == highlight )
		return;
    
    this._highlighted = highlight;
    
	if( this.highlightCallback ){
		this.highlightCallback(highlight,this.element);
	}	
}

dashcode.TouchButtonEventHandler.prototype._mousedown = function(event)
{
	if( (event.srcElement.tagName == "INPUT" || event.srcElement.tagName == "TEXTAREA") 
       && event.srcElement != this.element )
		return false;
    
	// If we're disabled, don't do anything
	if (!this.eventsEnabled || !this.actionCallback)
	{
		event.stopPropagation();
		event.preventDefault();
		return;
	}
	
	this._highlight(true);
	
	// add temp event listeners
	document.addEventListener("mousemove", this._mousemoveHandler, true);
	document.addEventListener("mouseup", this._mouseupHandler, true);
	this.element.addEventListener("mouseover", this._mouseoverHandler, true);
	this.element.addEventListener("mouseout", this._mouseoutHandler, true);
	
	this._inside = true;
	
	// We don't preventDefault() so that the focused view is properly blurred
	event.stopPropagation();
}

dashcode.TouchButtonEventHandler.prototype._mouseover = function(event)
{
	this._highlight(true);
	
	this._inside = true;
	
	event.stopPropagation();
	event.preventDefault();		
}

dashcode.TouchButtonEventHandler.prototype._mouseout = function(event)
{
	// Change images to regular state
	this._highlight(false);
	
	this._inside = false;
	
	event.stopPropagation();
	event.preventDefault();	
}

dashcode.TouchButtonEventHandler.prototype._mouseup = function(event)
{		
	// Change images to regular state
	this._highlight(false);
	
	// Remove temp event listeners
	document.removeEventListener("mousemove", this._mousemoveHandler, true);
	document.removeEventListener("mouseup", this._mouseupHandler, true);
	this.element.removeEventListener("mouseover", this._mouseoverHandler, true);
	this.element.removeEventListener("mouseout", this._mouseoutHandler, true);
	
	// Perform callback if we're inside the button
	try {
		if (this._inside && this.actionCallback != null)
            this._callActionCallback()			
	} catch(ex) {
		throw ex;
	} finally {
		event.stopPropagation();
		event.preventDefault();
		delete this._inside;
	}
}