/* 
 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();
}

//
// 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);
	}
    
	// Set up a blank onclick handler so that the keyboard is moved up when done
	this.element.onclick = function(event){
	};
	
    
}

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

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

dashcode.TouchButtonEventHandler.prototype._touchStart = function(event)
{
	var self = this;
	
	if( (event.srcElement.tagName == "INPUT" || event.srcElement.tagName == "TEXTAREA") 
       && 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{
		this._timeoutTimer = setTimeout(function(){ self._touchStartTimeout(event) },100);
	}
}

dashcode.TouchButtonEventHandler.prototype._touchStartTimeout = function(event)
{
	var self = this;
	
	delete this._timeoutTimer;
    
	this._highlight(true);
	
	this._inside = true;	
	
	if( !this._inTouchEvent )
		setTimeout(function(){ self._touchComplete(event,true); }, 100);
}

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( touchInElement ){
		this._inside = false;
		this._highlight(false);
	}else{
		this._inside = true;
		this._highlight(true);
		event.preventDefault();
	}
    
}

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 )
		this._touchComplete(event,true);
	else{
		clearTimeout(this._timeoutTimer);
		this._timeoutTimer = setTimeout(function(){ self._touchStartTimeout(event) },200);
	}
	
	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._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)
			this.actionCallback(event,this.element);
	} catch(ex) {
		throw ex;
	} finally {
		delete this._inside;
	}	
}

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

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;
	
	event.stopPropagation();
	event.preventDefault();
}

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.actionCallback(event);
	} catch(ex) {
		throw ex;
	} finally {
		event.stopPropagation();
		event.preventDefault();
		delete this._inside;
	}
}