﻿// README
//
// There are two steps to adding a property:
//
// 1. Create a member variable to store your property
// 2. Add the get_ and set_ accessors for your property
//
// Remember that both are case sensitive!


/// <reference name="MicrosoftAjaxTimer.debug.js" />
/// <reference name="MicrosoftAjaxWebForms.debug.js" />
/// <reference name="AjaxControlToolkit.ExtenderBase.BaseScripts.js" assembly="AjaxControlToolkit" />


Type.registerNamespace('Tooltip');

Tooltip.TooltipBehavior = function(element) {
    Tooltip.TooltipBehavior.initializeBase(this, [element]);

    // TODO : (Step 1) Add your property variables here
    this._servicePath = null;
    this._serviceMethod = null;
    this._contextKey = null;
    this._cacheDynamicResults = false;
    this._setUpdatingCssClass = null;
    this._clearDuringUpdate = true;
    this._customScript = null;
        
    this._callID = 0;
    this._currentCallID = -1;
    
    this._delay = null;
	 this._mouseoverHandler = null;
    this._mouseoutHandler = null;
    this._direction = null;
    this._timer = null;
    this._located = null;
    this._contents = null;
    this._tooltipEl = null;
    this._width = null;
    
    // Whether or not we've already populated (used for cacheDynamicResults)
    this._populated = false;
}

Tooltip.TooltipBehavior.prototype = {
    initialize : function() {
        Tooltip.TooltipBehavior.callBaseMethod(this, 'initialize');
        $common.prepareHiddenElementForATDeviceUpdate();  
        
        // hook up the trigger if we have one.
			this._mouseoverHandler = Function.createDelegate(this, (this._delay>0?this._onTargetElementDelayedMouseOver:this._onTargetElementMouseOver));
			this._focusHandler = Function.createDelegate(this, (this._delay>0?this._onTargetElementDelayedMouseOver:this._onTargetElementMouseOver));
			this._mouseoutHandler = Function.createDelegate(this, (this._delay>0?this._onTargetElementDelayedMouseOut:this._onTargetElementMouseOut));
				
        var element = this.get_element();
        if (element) {
				Sys.UI.DomEvent.addHandler(element, "mouseover", this._mouseoverHandler);
            Sys.UI.DomEvent.addHandler(element, "mouseout", this._mouseoutHandler);
				Sys.UI.DomEvent.addHandler(element, "focus", this._mouseoverHandler);
            Sys.UI.DomEvent.addHandler(element, "blur", this._mouseoutHandler);            
        }
        var tooltipEl = this.get_TooltipElement();
        if(tooltipEl)
        {
			// move tooltip to body
			//document.appendChild(tooltipEl);
			$common.setVisible(tooltipEl, false);
			Sys.UI.DomEvent.addHandler(tooltipEl, "mouseover", this._mouseoverHandler);
			Sys.UI.DomEvent.addHandler(tooltipEl, "mouseout", this._mouseoutHandler);
        }
        
        
    },
    dispose : function() {
        // TODO: Add your cleanup code here
        // clean up the trigger event.
        var element = this.get_element();
        var tooltipEl = this.get_TooltipElement();
        if (this._mouseoverHandler) {
            
            if (element) {
                Sys.UI.DomEvent.removeHandler(element, "mouseover", this._mouseoverHandler);
                Sys.UI.DomEvent.removeHandler(element, "focus", this._mouseoverHandler);
            }
            if (tooltipEl) {
                Sys.UI.DomEvent.removeHandler(tooltipEl, "mouseover", this._mouseoverHandler);
            }
            this._mouseoverHandler = null;
        }
        
         if (this._mouseoutHandler) {
            if (element) {
                Sys.UI.DomEvent.removeHandler(element, "mouseout", this._mouseoutHandler);
                Sys.UI.DomEvent.removeHandler(element, "blur", this._mouseoutHandler);
            }
            if (tooltipEl) {
                Sys.UI.DomEvent.removeHandler(tooltipEl, "mouseout", this._mouseoutHandler);
            }
            this._mouseoutHandler = null;
        }
        if(tooltipEl)
        {
				document.body.removeChild(tooltipEl);
				
        }
        Tooltip.TooltipBehavior.callBaseMethod(this, 'dispose');
    },

    populate : function(contextKey) {
        /// <summary>
        /// Get the dymanic content and use it to populate the target element
        /// </summary>
        /// <param name="contextKey" type="String" mayBeNull="true" optional="true">
        /// An arbitrary string value to be passed to the web method. For example, if the element to be
        /// populated is within a data-bound repeater, this could be the ID of the current row.
        /// </param>
        
        // Don't populate if we already cached the results
        if (this._populated && this._cacheDynamicResults) {
            return;
        }

        // Initialize the population if this is the very first call
        if (this._currentCallID == -1) {
            var eventArgs = new Sys.CancelEventArgs();
            this.raisePopulating(eventArgs);
            if (eventArgs.get_cancel()) {
                return;
            }
            this._setUpdating(true);
        }
        
        // Either run the custom population script or invoke the web service
        if (this._customScript) {
            // Call custom javascript call to populate control
            var scriptResult = eval(this._customScript);
            this.get_TooltipElement().firstChild.innerHTML = scriptResult; 
            this._setUpdating(false);
         } 
         else 
         {
             this._currentCallID = ++this._callID;
             if (this._servicePath && this._serviceMethod) {
                Sys.Net.WebServiceProxy.invoke(this._servicePath, this._serviceMethod, false,
                    { contextKey:(contextKey ? contextKey : this._contextKey) },
                    Function.createDelegate(this, this._onMethodComplete), Function.createDelegate(this, this._onMethodError),
                    this._currentCallID);
                $common.updateFormToRefreshATDeviceBuffer();
             }
        }
    },

    _onMethodComplete : function (result, userContext, methodName) {
        /// <summary>
        /// Callback used when the populating service returns successfully
        /// </summary>
        /// <param name="result" type="Object" mayBeNull="">
        /// The data returned from the Web service method call
        /// </param>
        /// <param name="userContext" type="Object">
        /// The context information that was passed when the Web service method was invoked
        /// </param>        
        /// <param name="methodName" type="String">
        /// The Web service method that was invoked
        /// </param>

        // ignore if it's not the current call.
        if (userContext != this._currentCallID) return;

        // Time has passed; make sure the element is still accessible
        var e = this.get_TooltipElement().firstChild;
        if (e) {
            e.innerHTML = result;
        }
        this._setUpdating(false);
        this._rltimer = window.setTimeout(Function.createDelegate(this,this._relocate),1);
        //this._relocate();
    },

    _onMethodError : function(webServiceError, userContext, methodName) {
        /// <summary>
        /// Callback used when the populating service fails
        /// </summary>
        /// <param name="webServiceError" type="Sys.Net.WebServiceError">
        /// Web service error
        /// </param>
        /// <param name="userContext" type="Object">
        /// The context information that was passed when the Web service method was invoked
        /// </param>        
        /// <param name="methodName" type="String">
        /// The Web service method that was invoked
        /// </param>

        // ignore if it's not the current call.
        if (userContext != this._currentCallID) return;

        var e = this.get_TooltipElement().firstChild;
        
        if (e) {
        
            if (webServiceError.get_timedOut()) {
                e.innerHTML = AjaxControlToolkit.Resources.DynamicPopulate_WebServiceTimeout;
            } else {
                e.innerHTML = String.format(AjaxControlToolkit.Resources.DynamicPopulate_WebServiceError, webServiceError.get_statusCode());
            }
        }
		  this._relocate();
        this._setUpdating(false);
    },
	_relocate : function(){
			var tooltipEl = this.get_TooltipElement();
		  var element = this.get_element();
		  
		  var bTooltip = Sys.UI.DomElement.getBounds(tooltipEl);
		  var bTarget = Sys.UI.DomElement.getBounds(element);
		  
			var iLeft = 0;var iTop=0;

		  if(this._direction==null){ // top
			  iLeft = parseInt((bTarget.x+(bTarget.width/2))-(bTooltip.width/2));
			  iTop = bTarget.y-bTooltip.height;
		  }
		  else if(this._direction=="2"){ // right
			iLeft = bTarget.x+bTarget.width;
			iTop = parseInt((bTarget.y+(bTarget.height/2))-(bTooltip.height/2));
		  }
		  else if(this._direction=="3"){ // bottom
			  iLeft = parseInt((bTarget.x+(bTarget.width/2))-(bTooltip.width/2));
			  iTop = bTarget.y+bTarget.height;
		  }
		  else if(this._direction=="4"){ // left
				iLeft = parseInt(bTarget.x-bTooltip.width);
				iTop = parseInt((bTarget.y+(bTarget.height/2))-(bTooltip.height/2));
		  }
		  else if(this._direction=="5"){ // cursor
		  }
		  Sys.UI.DomElement.setLocation(tooltipEl, iLeft, iTop);
	},
	_onTargetElementDelayedMouseOver : function(eventElement){
		if(this._timer){window.clearTimeout(this._timer);this._timer=null;}
		this._timer = window.setTimeout(Function.createDelegate(this,this._onTargetElementMouseOver),this._delay);
	},
    _onTargetElementMouseOver : function() {
        /// <summary>
        /// Handler for the element described by TargetControlID's mouseover event
        /// </summary>
		  // create our control - or get current visible element
		  if(this._timer) window.clearTimeout(this._timer);
		  var tooltipEl = this.get_TooltipElement();
		  if(!$common.getVisible(tooltipEl))
		  {
			  var element = this.get_element();
			  
			  var bTooltip = tooltipEl.bounds;
			  if(!bTooltip)
			  {
				tooltipEl.bounds = Sys.UI.DomElement.getBounds(tooltipEl);
				bTooltip = tooltipEl.bounds;
			  }
			  var bTarget = Sys.UI.DomElement.getBounds(element);
			  // ** assume bottom for now
			  
			  $common.setVisible(tooltipEl, true);
			  this._relocate();
		  
			  if(this._customScript || (this._servicePath && this._serviceMethod))
			  {
				// just call through to the trigger.
				this.populate(this._contextKey);		  
			  }
			}
    },
    	_onTargetElementDelayedMouseOut : function(eventElement){
		if(this._timer){window.clearTimeout(this._timer);this._timer=null;}
		this._timer = window.setTimeout(Function.createDelegate(this,this._onTargetElementMouseOut),this._delay);
	},

    _onTargetElementMouseOut : function(eventElement){
		if(this._timer) window.clearTimeout(this._timer);
		var tooltipEl = this.get_TooltipElement();
		  $common.setVisible(tooltipEl, false);
    },
    
    _setUpdating : function(updating) {
        /// <summary>
        /// Toggle the display elements to indicate if they are being updated or not
        /// </summary>
        /// <param name="updating" type="Boolean">
        /// Whether or not the display should indicated it is being updated
        /// </param>
        this.setStyle(updating);
        if (!updating) {
            this._currentCallID = -1;
            this._populated = true;
            this.raisePopulated(this, Sys.EventArgs.Empty);
        }
    },
    
    setStyle : function(updating) {
        /// <summary>
        /// Set the style of the display
        /// </summary>
        /// <param name="updating" type="Boolean">
        /// Whether or not the display is being updated
        /// </param>
        
        var e = this.get_TooltipElement().firstChild;
        if (this._setUpdatingCssClass) {
			
            if (!updating) {
                e.className = this._oldCss;
                this._oldCss = null;
            } else {
                this._oldCss = e.className;
                e.className = this._setUpdatingCssClass;
            }
        }
        if (updating && this._clearDuringUpdate) {
            e.innerHTML = "";
        }
    },
    
   
    get_ClearContentsDuringUpdate : function() {
        /// <value type="Boolean">
        /// Whether the contents of the target should be cleared when an update begins
        /// </value>
        return this._clearDuringUpdate;
    },
    set_ClearContentsDuringUpdate : function(value) {
        if (this._clearDuringUpdate != value) {
            this._clearDuringUpdate = value;
            this.raisePropertyChanged('ClearContentsDuringUpdate');
        }
    },
    
    get_ContextKey : function() {
        /// <value type="String">
        /// An arbitrary string value to be passed to the web method.
        /// For example, if the element to be populated is within a
        /// data-bound repeater, this could be the ID of the current row.
        /// </value>
        return this._contextKey;
    },
    set_ContextKey : function(value) {
        if (this._contextKey != value) {
            this._contextKey = value;
            this.raisePropertyChanged('ContextKey');
        }
    },
    
    get_PopulateTriggerID : function() {
        /// <value type="String" mayBeNull="true" optional="true">
        /// Name of an element that triggers the population of the target when clicked
        /// </value>
        return this._populateTriggerID;
    },
    set_PopulateTriggerID : function(value) {
        if (this._populateTriggerID != value) {
            this._populateTriggerID = value;
            this.raisePropertyChanged('PopulateTriggerID');
        }
    },
    
    get_TooltipElement :function()
    {
		// ** ensure tooltip available
		if(this._tooltipEl==null){
			this._tooltipEl = document.createElement("DIV");
			Sys.UI.DomElement.addCssClass(this._tooltipEl, "tooltip");

			if(this._width!=null && this._width>0)
			{
				this._tooltipEl.style.width = this._width;
			}
			
			var tooltipElBorder = document.createElement("DIV");
			Sys.UI.DomElement.addCssClass(tooltipElBorder, "border");
			this._tooltipEl.appendChild(tooltipElBorder);
			
			if(this._direction==null){ // top
				Sys.UI.DomElement.addCssClass(this._tooltipEl, "ttdirtop");  
		  }
		  else if(this._direction=="2"){ // right
			Sys.UI.DomElement.addCssClass(this._tooltipEl, "ttdirright");  
		  }
		  else if(this._direction=="3"){ // bottom
			  Sys.UI.DomElement.addCssClass(this._tooltipEl, "ttdirbottom");  
		  }
		  else if(this._direction=="4"){ // left
				Sys.UI.DomElement.addCssClass(this._tooltipEl, "ttdirleft"); 
		  }
		  
			var tooltipElContents = document.createElement("DIV");
			Sys.UI.DomElement.addCssClass(tooltipElContents, "contents");
			tooltipElBorder.appendChild(tooltipElContents);
			tooltipElContents.innerHTML = this._contents;
			
			var tooltipElCallout = document.createElement("DIV");
			Sys.UI.DomElement.addCssClass(tooltipElCallout, "callout");
			this._tooltipEl.appendChild(tooltipElCallout);
			
			document.body.appendChild(this._tooltipEl);
		}
		return this._tooltipEl;
    },
    
    get_ServicePath : function() {
        /// <value type="String" mayBeNull="true" optional="true">
        /// The URL of the web service to call.  If the ServicePath is not defined, then we will invoke a PageMethod instead of a web service.
        /// </value>
        return this._servicePath;
    },
    set_ServicePath : function(value) {
        if (this._servicePath != value) {
            this._servicePath = value;
            this.raisePropertyChanged('ServicePath');
        }
    },
    
    get_ServiceMethod : function() {
        /// <value type="String">
        /// The name of the method to call on the page or web service
        /// </value>
        /// <remarks>
        /// The signature of the method must exactly match the following:
        ///    [WebMethod]
        ///    string DynamicPopulateMethod(string contextKey)
        ///    {
        ///        ...
        ///    }
        /// </remarks>
        return this._serviceMethod;
    },
    set_ServiceMethod : function(value) {
        if (this._serviceMethod != value) {
            this._serviceMethod = value;
            this.raisePropertyChanged('ServiceMethod');
        }
    },
    
    get_cacheDynamicResults : function() {
        /// <value type="Boolean" mayBeNull="false">
        /// Whether the results of the dynamic population should be cached and
        /// not fetched again after the first load
        /// </value>
        return this._cacheDynamicResults;
    },
    set_cacheDynamicResults : function(value) {
        if (this._cacheDynamicResults != value) {
            this._cacheDynamicResults = value;
            this.raisePropertyChanged('cacheDynamicResults');
        }
    },
    
    get_UpdatingCssClass : function() {
        /// <value type="String">
        /// The CSS class to apply to the target during asynchronous calls
        /// </value>
        return this._setUpdatingCssClass;
    },
    set_UpdatingCssClass : function(value) {
        if (this._setUpdatingCssClass != value) {
            this._setUpdatingCssClass = value;
            this.raisePropertyChanged('UpdatingCssClass');
        }
    },
    
    get_CustomScript : function() {
        /// <value type="String">
        /// The script to invoke instead of calling a Web or Page method. This script must evaluate to a string value.
        /// </value>
        return this._customScript;
    },   
    set_CustomScript : function(value) {
        if (this._customScript != value) {
            this._customScript = value;
            this.raisePropertyChanged('CustomScript');
        }
    },
	 get_Contents : function() {
        /// <value type="String">
        /// The script to invoke instead of calling a Web or Page method. This script must evaluate to a string value.
        /// </value>
        return this._contents;
    },   
    set_Contents : function(value) {
        if (this._contents != value) {
            this._contents = value;
            this.raisePropertyChanged('Contents');
        }
    },
   get_Delay : function() {
        /// <value type="String">
        /// The script to invoke instead of calling a Web or Page method. This script must evaluate to a string value.
        /// </value>
        return this._delay;
    },   
    set_Delay : function(value) {
        if (this._delay != value) {
            this._delay = value;
            this.raisePropertyChanged('Delay');
        }
    }, 
	get_TooltipWidth : function() {
        /// <value type="String">
        /// The script to invoke instead of calling a Web or Page method. This script must evaluate to a string value.
        /// </value>
        return this._width;
    },   
    set_TooltipWidth : function(value) {
        if (this._width != value) {
            this._width = value;
            this.raisePropertyChanged('TooltipWidth');
        }
    }, 
   get_Direction : function() {
        /// <value type="String">
        /// The script to invoke instead of calling a Web or Page method. This script must evaluate to a string value.
        /// </value>
        return this._direction;
    },   
    set_Direction : function(value) {
        if (this._direction != value) {
            this._direction = value;
            this.raisePropertyChanged('Direction');
        }
    },
    add_populating : function(handler) {
        /// <summary>
        /// Add an event handler for the populating event
        /// </summary>
        /// <param name="handler" type="Function" mayBeNull="false">
        /// Event handler
        /// </param>
        /// <returns />
        this.get_events().addHandler('populating', handler);
    },
    remove_populating : function(handler) {
        /// <summary>
        /// Remove an event handler from the populating event
        /// </summary>
        /// <param name="handler" type="Function" mayBeNull="false">
        /// Event handler
        /// </param>
        /// <returns />
        this.get_events().removeHandler('populating', handler);
    },
    raisePopulating : function(eventArgs) {
        /// <summary>
        /// Raise the populating event
        /// </summary>
        /// <param name="eventArgs" type="Sys.CancelEventArgs" mayBeNull="false">
        /// Event arguments for the populating event
        /// </param>
        /// <returns />
        
        var handler = this.get_events().getHandler('populating');
        if (handler) {
            handler(this, eventArgs);
        }
    },
    
    add_populated : function(handler) {
        /// <summary>
        /// Add an event handler for the populated event
        /// </summary>
        /// <param name="handler" type="Function" mayBeNull="false">
        /// Event handler
        /// </param>
        /// <returns />
        this.get_events().addHandler('populated', handler);
    },
    remove_populated : function(handler) {
        /// <summary>
        /// Remove an event handler from the populated event
        /// </summary>
        /// <param name="handler" type="Function" mayBeNull="false">
        /// Event handler
        /// </param>
        /// <returns />
        this.get_events().removeHandler('populated', handler);
    },
    raisePopulated : function(eventArgs) {
        /// <summary>
        /// Raise the populated event
        /// </summary>
        /// <param name="eventArgs" type="Sys.EventArgs" mayBeNull="false">
        /// Event arguments for the populated event
        /// </param>
        /// <returns />
         
        var handler = this.get_events().getHandler('populated');
        if (handler) {
            handler(this, eventArgs);
        }
    }
}
Tooltip.TooltipBehavior.registerClass('Tooltip.TooltipBehavior', AjaxControlToolkit.BehaviorBase);

if(typeof(Sys)!=='undefined')Sys.Application.notifyScriptLoaded();