/* START Telerik.Web.UI.Common.Core.js */
// Avoids the background image flickering in IE 6 (http://www.mister-pixel.com/)
try
{
	document.execCommand("BackgroundImageCache", false, true);
}
catch(err) {}

Type.registerNamespace("Telerik.Web.UI");

window.$telerik = window.TelerikCommonScripts = Telerik.Web.CommonScripts = {
	
	_borderStyleNames : ['borderTopStyle','borderRightStyle','borderBottomStyle','borderLeftStyle'],
	_borderWidthNames : ['borderTopWidth', 'borderRightWidth', 'borderBottomWidth', 'borderLeftWidth'],
	_paddingWidthNames : ['paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft'],
	_marginWidthNames : ['marginTop', 'marginRight', 'marginBottom', 'marginLeft'],
	radControls : [],
	
	registerControl : function (control)
	{
		if (!Array.contains(this.radControls, control))
			Array.add(this.radControls, control);
	},
	
	unregisterControl : function (control)
	{
		Array.remove(this.radControls, control);
	},
	
	repaintChildren : function (parentControl)
	{
		var parentElement = parentControl.get_element();
		
		for (var i = 0, length = this.radControls.length; i < length; i ++)
		{
	        var control = this.radControls[i];
        
		    if (control.repaint && this.isDescendant(parentElement, control.get_element()))
				control.repaint();
		}
	},
	
	_borderThickness : function ()
	{
		$telerik._borderThicknesses = { };

		var div0 = document.createElement('div');
		var div1 = document.createElement('div');

		div0.style.visibility = 'hidden';
		div0.style.position = 'absolute';
		div0.style.fontSize = '1px';
	    
		div1.style.height = '0px';
		div1.style.overflow = 'hidden';
	    
		document.body.appendChild(div0).appendChild(div1);
	                    
		var base = div0.offsetHeight;
		div1.style.borderTop = 'solid black';        

		div1.style.borderTopWidth = 'thin';
		$telerik._borderThicknesses['thin'] = div0.offsetHeight - base;
	    
		div1.style.borderTopWidth = 'medium';
		$telerik._borderThicknesses['medium'] = div0.offsetHeight - base;
	    
		div1.style.borderTopWidth = 'thick';
		$telerik._borderThicknesses['thick'] = div0.offsetHeight - base;
	    
		if (typeof(div0.removeChild) !== "undefined")
			div0.removeChild(div1);
			
		document.body.removeChild(div0);
		div0 = null;
		div1 = null;
	},
	
	getCurrentStyle : function(element, attribute, defaultValue) {
     
        var currentValue = null;
        if (element) {
            if (element.currentStyle) {
                currentValue = element.currentStyle[attribute];
            } else if (document.defaultView && document.defaultView.getComputedStyle) {
                var style = document.defaultView.getComputedStyle(element, null);
                if (style) {
                    currentValue = style[attribute];
                }
            }
            
            if (!currentValue && element.style.getPropertyValue) {
                currentValue = element.style.getPropertyValue(attribute);
            }
            else if (!currentValue && element.style.getAttribute) {
                currentValue = element.style.getAttribute(attribute);
            }       
        }
        
        if ((!currentValue || currentValue == "" || typeof(currentValue) === 'undefined')) {
            if (typeof(defaultValue) != 'undefined') {
                currentValue = defaultValue;
            }
            else {
                currentValue = null;
            }
        }   
        return currentValue;  
    },
    
    getInheritedBackgroundColor : function(element) {
        if (!element) return '#FFFFFF';
        var background = $telerik.getCurrentStyle(element, 'backgroundColor');
        try {
            while (!background || background == '' || background == 'transparent' || background == 'rgba(0, 0, 0, 0)') {
                element = element.parentNode;
                if (!element) {
                    background = '#FFFFFF';
                } else {
                    background = $telerik.getCurrentStyle(element, 'backgroundColor');
                }
            }
        } catch(ex) {
            background = '#FFFFFF';
        }
        return background;
    },
    
	getLocation : function(element) {

		// workaround for an issue in getLocation where it will compute the location of the document element.
		// this will return an offset if scrolled.
		//
		if (element === document.documentElement) {
			return new Sys.UI.Point(0,0);
		}

		// Workaround for IE6 bug in getLocation (also required patching getBounds - remove that fix when this is removed)
		
		//TEKI: When in IE7 in a scenario when item is in a FRAMESET, the location value is wrong. However, using the IE6 code below it works fine
		if (Sys.Browser.agent == Sys.Browser.InternetExplorer /*&& Sys.Browser.version < 7*/) {
			if (element.window === element || element.nodeType === 9 || !element.getClientRects || !element.getBoundingClientRect) return new Sys.UI.Point(0,0);

			// Get the first bounding rectangle in screen coordinates
			var screenRects = element.getClientRects();
			if (!screenRects || !screenRects.length) {
				return new Sys.UI.Point(0,0);
			}
			var first = screenRects[0];

			// Delta between client coords and screen coords
			var dLeft = 0;
			var dTop = 0;

			var inFrame = false;
			try {
				inFrame = element.ownerDocument.parentWindow.frameElement;
			} catch(ex) {
				// If accessing the frameElement fails, a frame is probably in a different
				// domain than its parent - and we still want to do the calculation below
				inFrame = true;
			}

			// If we're in a frame, get client coordinates too so we can compute the delta
			if (inFrame) {
				// Get the bounding rectangle in client coords
				var clientRect = element.getBoundingClientRect();
				if (!clientRect) {
					return new Sys.UI.Point(0,0);
				}

				// Find the minima in screen coords
				var minLeft = first.left;
				var minTop = first.top;
				for (var i = 1; i < screenRects.length; i++) {
					var r = screenRects[i];
					if (r.left < minLeft) {
						minLeft = r.left;
					}
					if (r.top < minTop) {
						minTop = r.top;
					}
				}

				// Compute the delta between screen and client coords
				dLeft = minLeft - clientRect.left;
				dTop = minTop - clientRect.top;
			}

			// Subtract 2px, the border of the viewport (It can be changed in IE6 by applying a border style to the HTML element,
			// but this is not supported by ASP.NET AJAX, and it cannot be changed in IE7.), and also subtract the delta between
			// screen coords and client coords
			var ownerDocument = element.document.documentElement;
			
			var position = new Sys.UI.Point(first.left - 2 - dLeft + ownerDocument.scrollLeft, first.top - 2 - dTop + ownerDocument.scrollTop);

			if ($telerik.quirksMode)
			{						
				position.x += document.body.scrollLeft;
				position.y += document.body.scrollTop;
			}
			
			return position;
		}

		var position = Sys.UI.DomElement.getLocation(element);
		
		if ($telerik.isOpera)
		{
			var parent = element.offsetParent;
			
			while (parent && parent.tagName.toUpperCase() != 'BODY' 
				&& parent.tagName.toUpperCase() != 'HTML') 
			{
				position.x -= parent.scrollLeft;
				position.y -= parent.scrollTop;
				parent = parent.offsetParent;
			}
		}
		
		if ($telerik.isSafari)
		{
			var parent = element.parentNode;
			
			var parentTD = null;
			var parentTABLE = null;
			
			while (parent && parent.tagName.toUpperCase() != 'BODY' 
				&& parent.tagName.toUpperCase() != 'HTML') 
			{
				position.x -= parent.scrollLeft;
				position.y -= parent.scrollTop;
				
				// Workaround for a problem with parent TABLES - when you have a parent TABLE element with border,
				// Safari acts as if the TABLE/TD has no border and calculates X and Y incorrectly. 
				// That is why we need to add the borders manually. In case this is fixed in a future verion of the browser
				// we will need to remove this code.
				if($telerik.isSafari3 || $telerik.isSafari2)
				{
				    if(parent.tagName.toUpperCase() == "TD")
			        {
			            parentTD = parent;
			        }
                    else if(parent.tagName.toUpperCase() == "TABLE")
                    {
                        parentTABLE = parent;
                    }
                    
                    if(parentTD && parentTABLE)
                    {                
                        position.x += parseInt($telerik.getCurrentStyle(parentTABLE, 'borderTopWidth'));
                        position.y += parseInt($telerik.getCurrentStyle(parentTABLE, 'borderLeftWidth'));
                            
                        // In case the TABLE has borderCollapse:collapse, we need to take the borderWidth of either
                        // the TABLE or the TD.
                        if($telerik.getCurrentStyle(parentTABLE, 'borderCollapse') != 'collapse')
                        {
                            position.x += parseInt($telerik.getCurrentStyle(parentTD, 'borderTopWidth'));
                            position.y += parseInt($telerik.getCurrentStyle(parentTD, 'borderLeftWidth'));
                        }
                        
                        parentTD = null;
                        parentTABLE = null;
                    }
                    // In case we use getLocation for a TD element, we need to calculate the borderWidth of its TABLE
                    // only in case that TABLE has no borderCollapse:collapse.
                    else if(parentTABLE)
                    {
                        if($telerik.getCurrentStyle(parentTABLE, 'borderCollapse') != 'collapse')
                        {
                            position.x += parseInt($telerik.getCurrentStyle(parentTABLE, 'borderTopWidth'));
                            position.y += parseInt($telerik.getCurrentStyle(parentTABLE, 'borderLeftWidth'));
                        }
                        parentTABLE = null;
                    }
                }
                
                // END of Workaround for a problem with parent TABLES
				
				parent = parent.parentNode;
			}			
		}

		if ($telerik.isIE && $telerik.quirksMode)
		{
			position.x += document.body.scrollLeft;
			position.y += document.body.scrollTop;
		}

		return position;
	},

    setLocation : function(element, point) {
        Sys.UI.DomElement.setLocation(element, point.x, point.y);
    },
    
    getContentSize : function(element) {
        /// <summary>
        /// Gets the "content-box" size of an element.
        /// </summary>
        /// <param name="element" type="Sys.UI.DomElement" domElement="true">
        /// DOM element
        /// </param>
        /// <returns type="Object">
        /// Size of the element (in the form {width,height})
        /// </returns>
        /// <remarks>
        /// The "content-box" is the size of the content area *inside* of the borders and
        /// padding of an element. The "content-box" size does not include the margins around
        /// the element.
        /// </remarks>
        
        if (!element) {
            throw Error.argumentNull('element');
        }
        var size = $telerik.getSize(element);
        var borderBox = $telerik.getBorderBox(element);
        var paddingBox = $telerik.getPaddingBox(element);
        return {
            width :  size.width - borderBox.horizontal - paddingBox.horizontal,
            height : size.height - borderBox.vertical - paddingBox.vertical
        }
    },
    
    getSize : function(element) {
        /// <summary>
        /// Gets the "border-box" size of an element.
        /// </summary>
        /// <param name="element" type="Sys.UI.DomElement" domElement="true">
        /// DOM element
        /// </param>
        /// <returns type="Object">
        /// Size of the element (in the form {width,height})
        /// </returns>
        /// <remarks>
        /// The "border-box" is the size of the content area *outside* of the borders and
        /// padding of an element.  The "border-box" size does not include the margins around
        /// the element.
        /// </remarks>
        
        if (!element) {
            throw Error.argumentNull('element');
        }
        return {
            width:  element.offsetWidth,
            height: element.offsetHeight
        };
    },
    
    setContentSize : function(element, size) {
        /// <summary>
        /// Sets the "content-box" size of an element.
        /// </summary>
        /// <param name="element" type="Sys.UI.DomElement" domElement="true">
        /// DOM element
        /// </param>
        /// <param name="size" type="Object">
        /// Size of the element (in the form {width,height})
        /// </param>
        /// <remarks>
        /// The "content-box" is the size of the content area *inside* of the borders and
        /// padding of an element. The "content-box" size does not include the margins around
        /// the element.
        /// </remarks>
        
        if (!element) {
            throw Error.argumentNull('element');
        }
        if (!size) {
            throw Error.argumentNull('size');
        }
        // FF respects -moz-box-sizing css extension, so adjust the box size for the border-box
        if($telerik.getCurrentStyle(element, 'MozBoxSizing') == 'border-box' || $telerik.getCurrentStyle(element, 'BoxSizing') == 'border-box') {
            var borderBox = $telerik.getBorderBox(element);
            var paddingBox = $telerik.getPaddingBox(element);
            size = {
                width: size.width + borderBox.horizontal + paddingBox.horizontal,
                height: size.height + borderBox.vertical + paddingBox.vertical
            };
        }
        element.style.width = size.width.toString() + 'px';
        element.style.height = size.height.toString() + 'px';
    },
    
    setSize : function(element, size) {
        /// <summary>
        /// Sets the "border-box" size of an element.
        /// </summary>
        /// <remarks>
        /// The "border-box" is the size of the content area *outside* of the borders and 
        /// padding of an element.  The "border-box" size does not include the margins around
        /// the element.
        /// </remarks>
        /// <param name="element" type="Sys.UI.DomElement">DOM element</param>
        /// <param name="size" type="Object">Size of the element (in the form {width,height})</param>
        /// <returns />
        
        if (!element) {
            throw Error.argumentNull('element');
        }
        if (!size) {
            throw Error.argumentNull('size');
        }
        var borderBox = $telerik.getBorderBox(element);
        var paddingBox = $telerik.getPaddingBox(element);
        var contentSize = {
            width:  size.width - borderBox.horizontal - paddingBox.horizontal,
            height: size.height - borderBox.vertical - paddingBox.vertical
        };
        $telerik.setContentSize(element, contentSize);
    },
	
	getBounds : function(element) {
        /// <summary>Gets the coordinates, width and height of an element.</summary>
        /// <param name="element" domElement="true"/>
        /// <returns type="Sys.UI.Bounds">
        ///   A Bounds object with four fields, x, y, width and height, which contain the pixel coordinates,
        ///   width and height of the element.
        /// </returns>

        var offset = $telerik.getLocation(element);
        return new Sys.UI.Bounds(offset.x, offset.y, element.offsetWidth || 0, element.offsetHeight || 0);
    },
	
	setBounds : function(element, bounds) {
        /// <summary>
        /// Sets the "border-box" bounds of an element
        /// </summary>
        /// <param name="element" type="Sys.UI.DomElement" domElement="true">
        /// DOM element
        /// </param>
        /// <param name="bounds" type="Object">
        /// Bounds of the element (of the form {x,y,width,height})
        /// </param>
        /// <remarks>
        /// The "border-box" is the size of the content area *outside* of the borders and
        /// padding of an element.  The "border-box" size does not include the margins around
        /// the element.
        /// </remarks>
        
        if (!element) {
            throw Error.argumentNull('element');
        }
        if (!bounds) {
            throw Error.argumentNull('bounds');
        }
        $telerik.setSize(element, bounds);
        $telerik.setLocation(element, bounds);
    },
    
    getClientBounds : function() {
        /// <summary>
        /// Gets the width and height of the browser client window (excluding scrollbars)
        /// </summary>
        /// <returns type="Sys.UI.Bounds">
        /// Browser's client width and height
        /// </returns>

        var clientWidth;
        var clientHeight;
        switch(Sys.Browser.agent) {
            case Sys.Browser.InternetExplorer:
                clientWidth = document.documentElement.clientWidth;
                clientHeight = document.documentElement.clientHeight;
                if (clientWidth == 0 && clientHeight == 0)
                {
                    //no doctype. use the body settings
                    clientWidth = document.body.clientWidth;
                    clientHeight = document.body.clientHeight;
                }
                break;
            case Sys.Browser.Safari:
                clientWidth = window.innerWidth;
                clientHeight = window.innerHeight;
                break;
            case Sys.Browser.Opera:
                clientWidth = Math.min(window.innerWidth, document.body.clientWidth);
                clientHeight = Math.min(window.innerHeight, document.body.clientHeight);
                break;
            default:  // Sys.Browser.Firefox, etc.
                clientWidth = Math.min(window.innerWidth, document.documentElement.clientWidth);
                clientHeight = Math.min(window.innerHeight, document.documentElement.clientHeight);
                break;
        }
        return new Sys.UI.Bounds(0, 0, clientWidth, clientHeight);
    },
    
    getMarginBox : function(element) {
        /// <summary>
        /// Gets the entire margin box sizes.
        /// </summary>
        /// <param name="element" type="Sys.UI.DomElement" domElement="true">
        /// DOM element
        /// </param>
        /// <returns type="Object">
        /// Element's margin box sizes (of the form {top,left,bottom,right,horizontal,vertical})
        /// </returns>
        if (!element) {
            throw Error.argumentNull('element');
        }
        var box = {
            top: $telerik.getMargin(element, Telerik.Web.BoxSide.Top),
            right: $telerik.getMargin(element, Telerik.Web.BoxSide.Right),
            bottom: $telerik.getMargin(element, Telerik.Web.BoxSide.Bottom),
            left: $telerik.getMargin(element, Telerik.Web.BoxSide.Left)
        }
        
        box.horizontal = box.left + box.right;
        box.vertical = box.top + box.bottom;
        return box;
    },
    
    getPaddingBox : function(element) {
        /// <summary>
        /// Gets the entire padding box sizes.
        /// </summary>
        /// <param name="element" type="Sys.UI.DomElement" domElement="true">
        /// DOM element
        /// </param>
        /// <returns type="Object">
        /// Element's padding box sizes (of the form {top,left,bottom,right,horizontal,vertical})
        /// </returns>
        
        if (!element) {
            throw Error.argumentNull('element');
        }
        var box = {
            top: $telerik.getPadding(element, Telerik.Web.BoxSide.Top),
            right: $telerik.getPadding(element, Telerik.Web.BoxSide.Right),
            bottom: $telerik.getPadding(element, Telerik.Web.BoxSide.Bottom),
            left: $telerik.getPadding(element, Telerik.Web.BoxSide.Left)
        }
        box.horizontal = box.left + box.right;
        box.vertical = box.top + box.bottom;
        return box;
    },
    
    getBorderBox : function(element) {
        /// <summary>
        /// Gets the entire border box sizes.
        /// </summary>
        /// <param name="element" type="Sys.UI.DomElement" domElement="true">
        /// DOM element
        /// </param>
        /// <returns type="Object">
        /// Element's border box sizes (of the form {top,left,bottom,right,horizontal,vertical})
        /// </returns>
        
        if (!element) {
            throw Error.argumentNull('element');
        }
        var box = {
            top: $telerik.getBorderWidth(element, Telerik.Web.BoxSide.Top),
            right: $telerik.getBorderWidth(element, Telerik.Web.BoxSide.Right),
            bottom: $telerik.getBorderWidth(element, Telerik.Web.BoxSide.Bottom),
            left: $telerik.getBorderWidth(element, Telerik.Web.BoxSide.Left)
        }
        box.horizontal = box.left + box.right;
        box.vertical = box.top + box.bottom;
        return box;
    },

	isBorderVisible : function(element, boxSide) {
        /// <summary>
        /// Gets whether the current border style for an element on a specific boxSide is not 'none'.
        /// </summary>
        /// <param name="element" type="Sys.UI.DomElement" domElement="true">
        /// DOM element
        /// </param>
        /// <param name="boxSide" type="Telerik.Web.BoxSide">
        /// Side of the element
        /// </param>
        /// <returns type="Boolean">
        /// Whether the current border style for an element on a specific boxSide is not 'none'.
        /// </returns>
        
        if (!element) {
            throw Error.argumentNull('element');
        }
        if(boxSide < Telerik.Web.BoxSide.Top || boxSide > Telerik.Web.BoxSide.Left) {
            throw Error.argumentOutOfRange(String.format(Sys.Res.enumInvalidValue, boxSide, 'Telerik.Web.BoxSide'));
        }
        var styleName = $telerik._borderStyleNames[boxSide];
        var styleValue = $telerik.getCurrentStyle(element, styleName);
        return styleValue != "none";
    },
    getMargin : function(element, boxSide) {
        /// <summary>
        /// Gets the margin thickness of an element on a specific boxSide.
        /// </summary>
        /// <param name="element" type="Sys.UI.DomElement" domElement="true">
        /// DOM element
        /// </param>
        /// <param name="boxSide" type="Telerik.Web.BoxSide">
        /// Side of the element
        /// </param>
        /// <returns type="Number" integer="true">
        /// Margin thickness on the element's specified side
        /// </returns>
        
        if (!element) {
            throw Error.argumentNull('element');
        }
        if(boxSide < Telerik.Web.BoxSide.Top || boxSide > Telerik.Web.BoxSide.Left) {
            throw Error.argumentOutOfRange(String.format(Sys.Res.enumInvalidValue, boxSide, 'Telerik.Web.BoxSide'));
        }
        var styleName = $telerik._marginWidthNames[boxSide];
        var styleValue = $telerik.getCurrentStyle(element, styleName);

        try { return $telerik.parsePadding(styleValue); } catch(ex) { return 0; }
    },

    getBorderWidth : function(element, boxSide) {
        /// <summary>
        /// Gets the border thickness of an element on a specific boxSide.
        /// </summary>
        /// <param name="element" type="Sys.UI.DomElement" domElement="true">
        /// DOM element
        /// </param>
        /// <param name="boxSide" type="Telerik.Web.BoxSide">
        /// Side of the element
        /// </param>
        /// <returns type="Number" integer="true">
        /// Border thickness on the element's specified side
        /// </returns>
        
        if (!element) {
            throw Error.argumentNull('element');
        }
        if(boxSide < Telerik.Web.BoxSide.Top || boxSide > Telerik.Web.BoxSide.Left) {
            throw Error.argumentOutOfRange(String.format(Sys.Res.enumInvalidValue, boxSide, 'Telerik.Web.BoxSide'));
        }
        if(!$telerik.isBorderVisible(element, boxSide)) {
            return 0;
        }        
        var styleName = $telerik._borderWidthNames[boxSide];    
        var styleValue = $telerik.getCurrentStyle(element, styleName);
        return $telerik.parseBorderWidth(styleValue);
    },
    
    getPadding : function(element, boxSide) {
        /// <summary>
        /// Gets the padding thickness of an element on a specific boxSide.
        /// </summary>
        /// <param name="element" type="Sys.UI.DomElement" domElement="true">
        /// DOM element
        /// </param>
        /// <param name="boxSide" type="Telerik.Web.BoxSide">
        /// Side of the element
        /// </param>
        /// <returns type="Number" integer="true">
        /// Padding on the element's specified side
        /// </returns>
        
        if (!element) {
            throw Error.argumentNull('element');
        }
        if(boxSide < Telerik.Web.BoxSide.Top || boxSide > Telerik.Web.BoxSide.Left) {
            throw Error.argumentOutOfRange(String.format(Sys.Res.enumInvalidValue, boxSide, 'Telerik.Web.BoxSide'));
        }
        var styleName = $telerik._paddingWidthNames[boxSide];
        var styleValue = $telerik.getCurrentStyle(element, styleName);
        return $telerik.parsePadding(styleValue);
    },
    
    parseBorderWidth : function(borderWidth) {
        /// <summary>
        /// Parses a border-width string into a pixel size
        /// </summary>
        /// <param name="borderWidth" type="String" mayBeNull="true">
        /// Type of border ('thin','medium','thick','inherit',px unit,null,'')
        /// </param>
        /// <returns type="Number" integer="true">
        /// Number of pixels in the border-width
        /// </returns>
        
        if(borderWidth) {
            switch(borderWidth) {
                case 'thin':
                case 'medium':
                case 'thick':
                    return $telerik._borderThicknesses[borderWidth];
                case 'inherit':
                    return 0;
            }
            var unit = $telerik.parseUnit(borderWidth);
            return unit.size;
        }
        return 0;
    },
    
    parsePadding : function(padding) {
        /// <summary>
        /// Parses a padding string into a pixel size
        /// </summary>
        /// <param name="padding" type="String" mayBeNull="true">
        /// Padding to parse ('inherit',px unit,null,'')
        /// </param>
        /// <returns type="Number" integer="true">
        /// Number of pixels in the padding
        /// </returns>
        
        if(padding) {
            if(padding == 'inherit') {
                return 0;
            }
            var unit = $telerik.parseUnit(padding);
            return unit.size;
        }
        return 0;
    },
    
    parseUnit : function(value) {
        /// <summary>
        /// Parses a unit string into a unit object
        /// </summary>
        /// <param name="value" type="String" mayBeNull="true">
        /// Value to parse (of the form px unit,% unit,em unit,...)
        /// </param>
        /// <returns type="Object">
        /// Parsed unit (of the form {size,type})
        /// </returns>
        
        if (!value) {
            throw Error.argumentNull('value');
        }
        
        value = value.trim().toLowerCase();
        var l = value.length;
        var s = -1;
        for(var i = 0; i < l; i++) {
            var ch = value.substr(i, 1);
            if((ch < '0' || ch > '9') && ch != '-' && ch != '.' && ch != ',') {
                break;
            }
            s = i;
        }
        if(s == -1) {
            throw Error.create('No digits');
        }
        var type;
        var size;
        if(s < (l - 1)) {
            type = value.substring(s + 1).trim();
        } else {
            type = 'px';
        }
        size = parseFloat(value.substr(0, s + 1));
        if(type == 'px') {
            size = Math.floor(size);
        }
        return { 
            size: size,
            type: type
        };
    },
    
    containsPoint : function(rect, x, y) {
        /// <summary>
        /// Tests whether a point (x,y) is contained within a rectangle
        /// </summary>
        /// <param name="rect" type="Object">The rectangle</param>
        /// <param name="x" type="Number">The x coordinate of the point</param>
        /// <param name="y" type="Number">The y coordinate of the point</param>
        
        //ORIGINAL TOOLKIT SCRIPT CHANGE: instead of rect.height it was written rect.width (!!!) Clearly a major bug!!!!
        return x >= rect.x && x <= (rect.x + rect.width) && y >= rect.y && y <= (rect.y + rect.height);
    },

    isDescendant : function(ancestor, descendant) {
        /// <summary>
        /// Whether the specified element is a descendant of the ancestor
        /// </summary>
        /// <param name="ancestor" type="Sys.UI.DomElement">Ancestor node</param>
        /// <param name="descendant" type="Sys.UI.DomElement">Possible descendant node</param>
        /// <returns type="Boolean" />
        
        for (var n = descendant.parentNode; n != null; n = n.parentNode) {
            if (n == ancestor) return true;
        }
        return false;
    },
	
	isDescendantOrSelf : function(ancestor, descendant) {
        /// <summary>
        /// Whether the specified element is a descendant of the ancestor or the same as the ancestor
        /// </summary>
        /// <param name="ancestor" type="Sys.UI.DomElement">Ancestor node</param>
        /// <param name="descendant" type="Sys.UI.DomElement">Possible descendant node</param>
        /// <returns type="Boolean" />

        if (ancestor === descendant) 
            return true;
        return $telerik.isDescendant(ancestor, descendant);
    },
    
	setOuterHeight : function (element, height)
	{
		if (height <= 0 || height == "") 
		{
			element.style.height = "";
		} 
		else
		{
			element.style.height = height + "px";
			var diff = element.offsetHeight - height;
			var newHeight = height - diff;
			if (newHeight > 0) {
				element.style.height = newHeight + "px";
			} else {
				element.style.height = "";
			}
		}
	},
	
    setOpacity : function(element, value) {
        /// <summary>
        /// Set the element's opacity
        /// </summary>
        /// <param name="element" type="Sys.UI.DomElement" domElement="true">
        /// Element
        /// </param>
        /// <param name="value" type="Number">
        /// Opacity of the element
        /// </param>
        
        if (!element) {
            throw Error.argumentNull('element');
        }
        try
        {
            if (element.filters) {
                var filters = element.filters;
                var createFilter = true;
                if (filters.length !== 0) {
                    var alphaFilter = filters['DXImageTransform.Microsoft.Alpha'];
                    if (alphaFilter) {
                        createFilter = false;
                        alphaFilter.opacity = value * 100;
                    }
                }
                if (createFilter) {
                    element.style.filter = 'progid:DXImageTransform.Microsoft.Alpha(opacity=' + (value * 100) + ')';
                }
            }
            else {
                element.style.opacity = value;
            }
        }
        catch (ex) {}
    },
    	
    getOpacity : function(element) {
        /// <summary>
        /// Get the element's opacity
        /// </summary>
        /// <param name="element" type="Sys.UI.DomElement" domElement="true">
        /// Element
        /// </param>
        /// <returns type="Number">
        /// Opacity of the element
        /// </returns>
        
        if (!element) {
            throw Error.argumentNull('element');
        }
        
        var hasOpacity = false;
        var opacity;
        
        try
        {
            if (element.filters) {
                var filters = element.filters;
                if (filters.length !== 0) {
                    var alphaFilter = filters['DXImageTransform.Microsoft.Alpha'];
                    if (alphaFilter) {
                        opacity = alphaFilter.opacity / 100.0;
                        hasOpacity = true;
                    }
                }
            }
            else {
                opacity = $telerik.getCurrentStyle(element, 'opacity', 1);
                hasOpacity = true;
            }
        }
        catch (ex) {}
        
        if (hasOpacity === false) {
            return 1.0;
        }
        return parseFloat(opacity);
    },

    addCssClasses : function(element, classNames) {
        /// <summary>
        /// Adds multiple css classes to a DomElement
        /// </summary>
        /// <param name="element" type="Sys.UI.DomElement">The element to modify</param>
        /// <param name="classNames" type="Array">The class names to add</param>
        
        for(var i = 0; i < classNames.length; i++) {
            Sys.UI.DomElement.addCssClass(element, classNames[i]);
        }
    },
    
    removeCssClasses : function(element, classNames) {
        /// <summary>
        /// Removes multiple css classes to a DomElement
        /// </summary>
        /// <param name="element" type="Sys.UI.DomElement">The element to modify</param>
        /// <param name="classNames" type="Array">The class names to remove</param>
        
        for(var i = 0; i < classNames.length; i++) {
            Sys.UI.DomElement.removeCssClass(element, classNames[i]);
        }
    },    	
	setOuterWidth : function (element, width)
	{
		if (width <= 0 || width == "") 
		{
			element.style.width = "";
		}
		else
		{
			element.style.width = width + "px";
			var diff = element.offsetWidth - width;
			var newWidth = width - diff;
			if (newWidth > 0) {
				element.style.width = newWidth + "px";
			} else {
				element.style.width = "";
			}
		}
	},
	
	getScrollOffset : function(element, recursive)
	{
		var left = 0;
		var top = 0;
		var parent = element;

		while (parent != null && parent.scrollLeft != null) {
			left += parent.scrollLeft;
			top += parent.scrollTop;
			// Don't include anything below the body. 
			if (!recursive || (parent == document.body && (parent.scrollLeft != 0 || parent.scrollTop != 0)))
				break;

			parent = parent.parentNode;
		}

		return { x: left, y: top };
	},
	
	getElementByClassName : function(element, className, tagName)
	{
		var children = null;
		if (tagName)
		{
			children = element.getElementsByTagName(tagName);
		}
		else
		{
			children = element.getElementsByTagName("*");
		}
	    
		for (var i = 0, length = children.length; i < length; i++)
		{
			var child = children[i];
	        
			if (Sys.UI.DomElement.containsCssClass(child, className))
			{
				return child;
			}
		}
	    
		return null;
	},
	
	//The $addHandler and $removeHandler only work with DOM HTML elements.
	//In products that use iframes (RadWindow, RadEditor, EditorPopup) events need to be attached to the iframes' document and/or contentWindow.
	//In addition to this to construct an event object, the MS AJAX framework attempts to use the window.event - which is null in the main page, when the event originates from a child frame
	//Thus, the need to provide an alternative to the MS AJAX framework arises
	addExternalHandler : function(element, eventName, handler)
	{        	
		if (element.addEventListener)
		{
			element.addEventListener(eventName, handler, false);
		}
		else if (element.attachEvent)
		{	
			element.attachEvent("on" + eventName, handler);
		}
	},
	removeExternalHandler : function(element, eventName, handler)
	{    	
		if (element.addEventListener)
		{
			element.removeEventListener(eventName, handler, false);
		}
		else if (element.detachEvent)
		{
			element.detachEvent("on" + eventName, handler);
		}
	},
	
	cancelRawEvent : function(e)
	{    	
		if (!e) return false;
		if (e.preventDefault) e.preventDefault();
		if (e.stopPropagation) e.stopPropagation();
		e.cancelBubble = true;
		e.returnValue = false;	
		return false;
	},
	
	getOuterHtml : function(element)
	{
		if (element.outerHTML)
		{
			return element.outerHTML;
		}
		else
		{
			var elementCopy = element.cloneNode(true);
			var tmpDiv = element.ownerDocument.createElement("DIV");
			tmpDiv.appendChild(elementCopy);
			return tmpDiv.innerHTML;		
		}
	},
	
	setVisible : function(e, value) 
	{
		if (!e) return;

		if (value != $telerik.getVisible(e)) {
	        
			if (value) {
				if (e.style.removeAttribute) {
					e.style.removeAttribute("display");
				} else {
				   e.style.removeProperty("display");
				}
			}
			else {
				e.style.display = 'none';
			}
	        
			e.style.visibility = value ? 'visible' : 'hidden';
		}
	},
	
	getVisible : function(e) 
	{
		if (!e) return false;

		return (("none" != $telerik.getCurrentStyle(e, "display")) &&
        ("hidden" != $telerik.getCurrentStyle(e, "visibility")));
	},
	
	getViewPortSize : function()
	{
		var width = 0;
		var height = 0;

		var canvas = document.body;

		if (!$telerik.quirksMode && !$telerik.isSafari)
		{
			canvas = document.documentElement;
		}

		if (window.innerWidth)
		{
			width = window.innerWidth;
			height = window.innerHeight;
		}
		else
		{
			width = canvas.clientWidth;
			height = canvas.clientHeight;
		}

		width += canvas.scrollLeft;
		height += canvas.scrollTop;

		return { width : width - 6, height : height - 6 };
	},
	
	elementOverflowsTop : function (element)
	{
		return $telerik.getLocation(element).y < 0;
	}, 

	elementOverflowsLeft : function (element)
	{
		return $telerik.getLocation(element).x < 0;
	},

	elementOverflowsBottom : function (screenSize, element)
	{
		var bottomEdge = $telerik.getLocation(element).y + element.offsetHeight;
		return bottomEdge > screenSize.height;
	},

	elementOverflowsRight : function (screenSize, element)
	{
		var rightEdge = $telerik.getLocation(element).x + element.offsetWidth;
		return rightEdge > screenSize.width;
	},

	getDocumentRelativeCursorPosition : function(e)
	{
		var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft;
		var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
		var left = e.clientX + scrollLeft;
		var top = e.clientY + scrollTop;
		return {left:left, top:top};
	},
	
//	//Lini: this code is not needed anymore. It will be removed for the Q1 2008 release.
//	makeCompatible : function(type)
//	{
//		/// <exclude />
//		/// <summary>
//		///		Doubles the get_propertyName, set_propertyName, add_event, remove_event
//		///		methods with get_PropertyName, set_PropertyName, etc. ones, to save troubles for
//		///		users already having client-side code with the mistaken client-side convention.
//		///
//		///     Doubles the methodName(...) with MethodName(...) member to save troubles for
//	    ///		users already having client-side code with the mistaken client-side convention.
//		/// </summary>

//		var proto = type.prototype;
//		for (var memberName in proto)
//		{
//			if (/([gs]et|add|remove|raise)_[a-z].*/.test(memberName))
//			{
//				var propNameStart = RegExp.$1.length + 1;
//				var oldPropName = memberName.substr(0, propNameStart) + memberName.charAt(propNameStart).toUpperCase() + memberName.substr(propNameStart + 1);
//				proto[oldPropName] = proto[memberName];
//			}
//			else if (/^[a-z][a-zA-Z]+$/.test(memberName) && 
//		             proto.hasOwnProperty(memberName) &&
//		             typeof(proto[memberName]) == "function" && 
//		             memberName != "initialize" &&
//		             memberName != "dispose")
//		    {
//		        var oldMethodName = memberName.charAt(0).toUpperCase() + memberName.substr(1);
//		        proto[oldMethodName] = proto[memberName];		    
//		    }
//		}
//	},
	
	getFirstChildByTagName : function (element, tagName, index)
	{
		if (!element || !element.childNodes)
		{
			return null;
		}
		
		var currentNode = element.childNodes[index] || element.firstChild;
		
		while (currentNode)
		{
			if (currentNode.nodeType == 1 && currentNode.tagName.toLowerCase() == tagName)
				return currentNode;
			
			currentNode = currentNode.nextSibling;
		}
	
		return null;
	},

	getChildByClassName : function(element, className, index)
	{
		var currentNode = element.childNodes[index] || element.firstChild;
		while (currentNode)
		{
			if (currentNode.nodeType == 1 && currentNode.className.indexOf(className) > -1)
				return currentNode;
			currentNode = currentNode.nextSibling;
		}
		return null;
	},

	getChildrenByTagName : function (element, tagName)
	{
		var children = new Array();
		var childNodes = element.childNodes;
		for (var i = 0, length = childNodes.length; i < length; i++)
		{
			var child = childNodes[i];
			if (child.nodeType == 1 && child.tagName.toLowerCase() == tagName)
				Array.add(children, child);
		}
		return children;
	},
	
	getChildrenByClassName : function (element, className)
	{
		var children = new Array();
		var childNodes = element.childNodes;
		for (var i = 0, length = childNodes.length; i < length; i++)
		{
			var child = childNodes[i];
			if (child.nodeType == 1 && child.className.indexOf(className) > -1)
				Array.add(children, child);
		}
		return children;
	}
}

$telerik.isIE = Sys.Browser.agent == Sys.Browser.InternetExplorer;
$telerik.isIE7 = $telerik.isIE && Sys.Browser.version == 7;
$telerik.isIE6 = $telerik.isIE && Sys.Browser.version < 7;
$telerik.isOpera = Sys.Browser.agent == Sys.Browser.Opera;
$telerik.isSafari = Sys.Browser.agent == Sys.Browser.Safari;
$telerik.isSafari3 = $telerik.isSafari && Sys.Browser.version > 500;
$telerik.isSafari2 = $telerik.isSafari && Sys.Browser.version <= 500;
$telerik.isFirefox = Sys.Browser.agent == Sys.Browser.Firefox;
$telerik.quirksMode = $telerik.isIE && document.compatMode != "CSS1Compat";
$telerik.standardsMode = !$telerik.quirksMode;

//Initialize the thickness of borders based on their style
$telerik._borderThickness();

Telerik.Web.UI.Orientation = function() {
    /// <summary>
    /// The Telerik.Web.UI.Orientation enumeration is used to specify 
    /// the orientation of a given asset
    /// </summary>
    /// <field name="Horizontal" type="Number" integer="true"/>
    /// <field name="Vertical" type="Number" integer="true"/>
    throw Error.invalidOperation();
}
Telerik.Web.UI.Orientation.prototype = {
    Horizontal : 0,
    Vertical : 1
} 
Telerik.Web.UI.Orientation.registerEnum('Telerik.Web.UI.Orientation', false);

Telerik.Web.UI.RadWebControl = function(element) 
{
    Telerik.Web.UI.RadWebControl.initializeBase(this, [element]);
    
    this._clientStateFieldID = null;
}

Telerik.Web.UI.RadWebControl.prototype = 
{
    initialize: function() 
    {
        Telerik.Web.UI.RadWebControl.callBaseMethod(this, 'initialize');
        
        $telerik.registerControl(this);
        
        if(!this.get_clientStateFieldID()) return;
        
        var input = $get(this.get_clientStateFieldID());    
        
        if(!input) return;
        
        input.setAttribute('autocomplete', 'off');
    },
    
    dispose: function() 
    {
        $telerik.unregisterControl(this);
        
        Telerik.Web.UI.RadWebControl.callBaseMethod(this, 'dispose');
    },
    
    raiseEvent : function(eventName, eventArgs) {
        /// <summary>
        /// Raise the event
        /// </summary>
        /// <param name="eventName" type="String" mayBeNull="false">
        /// Name of the event to be raised
        /// </param>
        /// <param name="eventArgs" type="Sys.EventArgs" mayBeNull="true">
        /// Event arguments for the given event
        /// </param>
        /// <returns />

		var handler = this.get_events().getHandler(eventName);
		if (handler) {
			if (!eventArgs) {
				eventArgs = Sys.EventArgs.Empty;
			}
			handler(this, eventArgs);
        }
    },
    
    updateClientState: function()
    {
        /// <summary>
        /// Call this function to update the client state hidden field.
        /// Use this function with caution, because it is resource hungry.
        /// </summary>
		this.set_clientState(this.saveClientState());
    },
    
    saveClientState: function()
    {
        /// <summary>
        /// This function should return the serialized client state of the control.
        /// </summary>
        /// <example>
		/// saveClientState: function()
		/// {
		///		var state = 
		///		{
		///			Collapsed	: this.get_collapsed(),
		///			Width		: this.get_width(),
		///			Height		: this.get_height()
		///		};
		///		return Sys.Serialization.JavaScriptSerializer.serialize(state);
		/// }
        /// </example>
         return null;
    },
    
    get_clientStateFieldID : function() 
    {
        /// <value type="String">
        /// ID of the hidden field used to store the client state
        /// </value>
        return this._clientStateFieldID;
    },
    set_clientStateFieldID : function(value) 
    {
        if (this._clientStateFieldID != value) 
        {
            this._clientStateFieldID = value;
            this.raisePropertyChanged('ClientStateFieldID');
        }
    },

    get_clientState : function() {
        /// <value type="String">
        /// Client state
        /// </value>
        if (this._clientStateFieldID) 
        {
            var input = document.getElementById(this._clientStateFieldID);
            if (input) 
            {
                return input.value;
            }
        }
        return null;
    },
    set_clientState : function(value) 
    {
        if (this._clientStateFieldID) 
        {
            var input = document.getElementById(this._clientStateFieldID);
            if (input) 
            {
                input.value = value;
            }
        }
    },
    
    _getChildElement : function(id)
	{
		return $get(this.get_id() + "_" + id);
	},
	
	_findChildControl : function(id)
	{
		return $find(this.get_id() + "_" + id);
	}
}

Telerik.Web.UI.RadWebControl.registerClass('Telerik.Web.UI.RadWebControl', Sys.UI.Control);

Telerik.Web.Timer = function() {
    Telerik.Web.Timer.initializeBase(this);
    
    this._interval = 1000;
    this._enabled = false;
    this._timer = null;
    
    this._timerCallbackDelegate = Function.createDelegate(this, this._timerCallback);
}

Telerik.Web.Timer.prototype = {
    get_interval: function() {
        
        return this._interval;
    },
    set_interval: function(value) {
        
        if (this._interval !== value) {
            this._interval = value;
            this.raisePropertyChanged('interval');
            
            if (!this.get_isUpdating() && (this._timer !== null)) {
                this._stopTimer();
                this._startTimer();
            }
        }
    },
    
    get_enabled: function() {
        
        return this._enabled;
    },
    set_enabled: function(value) {
        
        if (value !== this.get_enabled()) {
            this._enabled = value;
            this.raisePropertyChanged('enabled');
            if (!this.get_isUpdating()) {
                if (value) {
                    this._startTimer();
                }
                else {
                    this._stopTimer();
                }
            }
        }
    },

    
    add_tick: function(handler) {
        this.get_events().addHandler("tick", handler);
    },

    remove_tick: function(handler) {
        this.get_events().removeHandler("tick", handler);
    },

    dispose: function() {
        this.set_enabled(false);
        this._stopTimer();
        
        Telerik.Web.Timer.callBaseMethod(this, 'dispose');
    },
    
    updated: function() {
        Telerik.Web.Timer.callBaseMethod(this, 'updated');

        if (this._enabled) {
            this._stopTimer();
            this._startTimer();
        }
    },

    _timerCallback: function() {
        var handler = this.get_events().getHandler("tick");
        if (handler) {
            handler(this, Sys.EventArgs.Empty);
        }
    },

    _startTimer: function() {
        this._timer = window.setInterval(this._timerCallbackDelegate, this._interval);
    },

    _stopTimer: function() {
        window.clearInterval(this._timer);
        this._timer = null;
    }
}

Telerik.Web.Timer.registerClass('Telerik.Web.Timer', Sys.Component);

Telerik.Web.BoxSide = function() {
}
Telerik.Web.BoxSide.prototype = {
    Top : 0,
    Right : 1,
    Bottom : 2,
    Left : 3
}
Telerik.Web.BoxSide.registerEnum("Telerik.Web.BoxSide", false);

if (Sys.CultureInfo.prototype._getAbbrMonthIndex) {
    try {
        Sys.CultureInfo.prototype._getAbbrMonthIndex('');
    } catch(ex) {
        Sys.CultureInfo.prototype._getAbbrMonthIndex = function(value) {
            if (!this._upperAbbrMonths) {
                this._upperAbbrMonths = this._toUpperArray(this.dateTimeFormat.AbbreviatedMonthNames);
            }
            return Array.indexOf(this._upperAbbrMonths, this._toUpper(value));
        }
        Sys.CultureInfo.CurrentCulture._getAbbrMonthIndex = Sys.CultureInfo.prototype._getAbbrMonthIndex;
        Sys.CultureInfo.InvariantCulture._getAbbrMonthIndex = Sys.CultureInfo.prototype._getAbbrMonthIndex;
    }
}

Type.registerNamespace("Telerik.Web.UI.Dialogs");

Telerik.Web.IParameterConsumer = function() {
}
Telerik.Web.IParameterConsumer.prototype = {
    clientInit: function(parameters) { throw Error.notImplemented(); }
}
Telerik.Web.IParameterConsumer.registerInterface('Telerik.Web.IParameterConsumer');

Telerik.Web.UI.Dialogs.CommonDialogScript = function()
{
}
Telerik.Web.UI.Dialogs.CommonDialogScript.get_windowReference = function()
{
	if (window.radWindow)
	{
		return window.radWindow;
	}
	if (window.frameElement && window.frameElement.radWindow)
	{
		return window.frameElement.radWindow;
	}
	return null;
};

Telerik.Web.UI.Dialogs.CommonDialogScript.registerClass('Telerik.Web.UI.Dialogs.CommonDialogScript', null);

Telerik.Web.UI.WebServiceLoaderEventArgs = function(context)
{
	Telerik.Web.UI.WebServiceLoaderEventArgs.initializeBase(this);
	this._context = context;
}

Telerik.Web.UI.WebServiceLoaderEventArgs.prototype =
{
	get_context : function ()
	{
		return this._context;
	}
}

Telerik.Web.UI.WebServiceLoaderEventArgs.registerClass('Telerik.Web.UI.WebServiceLoaderEventArgs', Sys.EventArgs);


// ---------- WebServiceLoaderSuccessEventArgs Class ----------
Telerik.Web.UI.WebServiceLoaderSuccessEventArgs = function(data, context)
{
	Telerik.Web.UI.WebServiceLoaderSuccessEventArgs.initializeBase(this, [context]);
	this._data = data;
}

Telerik.Web.UI.WebServiceLoaderSuccessEventArgs.prototype =
{
	get_data : function ()
	{
		return this._data;
	}	
}

Telerik.Web.UI.WebServiceLoaderSuccessEventArgs.registerClass('Telerik.Web.UI.WebServiceLoaderSuccessEventArgs', Telerik.Web.UI.WebServiceLoaderEventArgs);


// ---------- WebServiceLoaderErrorEventArgs Class ----------
Telerik.Web.UI.WebServiceLoaderErrorEventArgs = function(message, context)
{
	Telerik.Web.UI.WebServiceLoaderErrorEventArgs.initializeBase(this, [context]);
	this._message = message;
}

Telerik.Web.UI.WebServiceLoaderErrorEventArgs.prototype =
{
	get_message : function ()
	{
		return this._message;
	}
}

Telerik.Web.UI.WebServiceLoaderErrorEventArgs.registerClass('Telerik.Web.UI.WebServiceLoaderErrorEventArgs', Telerik.Web.UI.WebServiceLoaderEventArgs);


// ---------- WebServiceLoader Class ----------
Telerik.Web.UI.WebServiceLoader = function(webServiceSettings)
{
	this._webServiceSettings = webServiceSettings;
	this._events = null;
	this._currentWebRequest = null;
	this._onWebServiceSuccessDelegate = Function.createDelegate(this, this._onWebServiceSuccess);
	this._onWebServiceErrorDelegate = Function.createDelegate(this, this._onWebServiceError);
}

Telerik.Web.UI.WebServiceLoader.prototype =
{
	// Public properties
	get_webServiceSettings : function ()
	{
		return this._webServiceSettings;
	},
	
	get_events: function ()
	{
		if (!this._events)
		{
			this._events = new Sys.EventHandlerList();
		}
		
		return this._events;
	},
	
	
	// Public methods
	loadData : function (params, context)
	{
		var webServiceSettings = this.get_webServiceSettings();
		
		if (webServiceSettings.get_isEmpty())
		{
			Error.invalidOperation("Please, specify valid web service and method.");
			return;
		}

		var webServicePath = webServiceSettings.get_path();
		var webMethod = webServiceSettings.get_method();
		
		this._raiseEvent("loadingStarted", new Telerik.Web.UI.WebServiceLoaderEventArgs(context));

		this._currentWebRequest =	Sys.Net.WebServiceProxy.invoke(webServicePath, webMethod, false, params,
										this._onWebServiceSuccessDelegate, this._onWebServiceErrorDelegate, context);
	},
	
	
	// Events
	add_loadingStarted : function(handler)
	{
		this.get_events().addHandler("loadingStarted", handler);
	},

	add_loadingError : function(handler)
	{
		this.get_events().addHandler("loadingError", handler);
	},

	add_loadingSuccess : function(handler)
	{
		this.get_events().addHandler("loadingSuccess", handler);
	},
	
	
	// Private methods	
	_onWebServiceSuccess : function (data, context)
	{
		var successEventArgs = new Telerik.Web.UI.WebServiceLoaderSuccessEventArgs(data, context);
		this._raiseEvent("loadingSuccess", successEventArgs);
	},
	
	_onWebServiceError : function (error, context)
	{	
		var errorEventArgs = new Telerik.Web.UI.WebServiceLoaderErrorEventArgs(error.get_message(), context);
		this._raiseEvent("loadingError", errorEventArgs);
	},

	_raiseEvent : function (eventName, eventArgs)
	{
		var handler = this.get_events().getHandler(eventName);        

		if (handler)
		{
			if (!eventArgs)
			{
				eventArgs = Sys.EventArgs.Empty;
			}

			handler(this, eventArgs);
		}
	}
}

Telerik.Web.UI.WebServiceLoader.registerClass('Telerik.Web.UI.WebServiceLoader');

Telerik.Web.UI.WebServiceSettings = function(serializedWebServiceSettings)
{
	this._path = null;
	this._method = null;
	
	//Add a check for the parameter existance
	if (!serializedWebServiceSettings) serializedWebServiceSettings = {};
	
	if (typeof(serializedWebServiceSettings.path) != "undefined")
	{
		this._path = serializedWebServiceSettings.path;
	}
	
	if (typeof(serializedWebServiceSettings.method) != "undefined")
	{
		this._method = serializedWebServiceSettings.method;
	}
}

Telerik.Web.UI.WebServiceSettings.prototype =
{
	get_path : function ()
	{
		return this._path;
	},
	
	set_path : function(value)
	{
		this._path = value;
	},

	get_method : function ()
	{
		return this._method;
	},
	
	set_method : function(value)
	{
		this._method = value;
	},
	
	get_isEmpty : function ()
	{
		/// <value type="Boolean">
		///		A value indicating wether the web service settings contain
		///		a non-null and non-empty service path and method.
		/// </value>
		var path = this.get_path();
		var method = this.get_method();
		
		return (!(path && method))
	}
}

Telerik.Web.UI.WebServiceSettings.registerClass('Telerik.Web.UI.WebServiceSettings');

/* END Telerik.Web.UI.Common.Core.js */
/* START Telerik.Web.UI.Common.Popup.BehaviorBase.js */
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Permissive License.
// See http://www.microsoft.com/resources/sharedsource/licensingbasics/sharedsourcelicenses.mspx.
// All other rights reserved.


Type.registerNamespace('Telerik.Web');

// This is the base behavior for all extender behaviors
Telerik.Web.BehaviorBase = function(element) {
    /// <summary>
    /// Base behavior for all extender behaviors
    /// </summary>
    /// <param name="element" type="Sys.UI.DomElement" domElement="true">
    /// Element the behavior is associated with
    /// </param>
    Telerik.Web.BehaviorBase.initializeBase(this,[element]);
    
    this._clientStateFieldID = null;
    this._pageRequestManager = null;
    this._partialUpdateBeginRequestHandler = null;
    this._partialUpdateEndRequestHandler = null;
}
Telerik.Web.BehaviorBase.prototype = {
    initialize : function() {
        /// <summary>
        /// Initialize the behavior
        /// </summary>

        // TODO: Evaluate necessity
        Telerik.Web.BehaviorBase.callBaseMethod(this, 'initialize');
    },

    dispose : function() {
        /// <summary>
        /// Dispose the behavior
        /// </summary>
        Telerik.Web.BehaviorBase.callBaseMethod(this, 'dispose');

        if (this._pageRequestManager) {
            if (this._partialUpdateBeginRequestHandler) {
                this._pageRequestManager.remove_beginRequest(this._partialUpdateBeginRequestHandler);
                this._partialUpdateBeginRequestHandler = null;
            }
            if (this._partialUpdateEndRequestHandler) {
                this._pageRequestManager.remove_endRequest(this._partialUpdateEndRequestHandler);
                this._partialUpdateEndRequestHandler = null;
            }
            this._pageRequestManager = null;
        }
    },

    get_ClientStateFieldID : function() {
        /// <value type="String">
        /// ID of the hidden field used to store client state
        /// </value>
        return this._clientStateFieldID;
    },
    set_ClientStateFieldID : function(value) {
        if (this._clientStateFieldID != value) {
            this._clientStateFieldID = value;
            this.raisePropertyChanged('ClientStateFieldID');
        }
    },

    get_ClientState : function() {
        /// <value type="String">
        /// Client state
        /// </value>
        if (this._clientStateFieldID) {
            var input = document.getElementById(this._clientStateFieldID);
            if (input) {
                return input.value;
            }
        }
        return null;
    },
    set_ClientState : function(value) {
        if (this._clientStateFieldID) {
            var input = document.getElementById(this._clientStateFieldID);
            if (input) {
                input.value = value;
            }
        }
    },

    registerPartialUpdateEvents : function() {
        /// <summary>
        /// Register for beginRequest and endRequest events on the PageRequestManager,
        /// (which cause _partialUpdateBeginRequest and _partialUpdateEndRequest to be
        /// called when an UpdatePanel refreshes)
        /// </summary>

        if (Sys && Sys.WebForms && Sys.WebForms.PageRequestManager){
            this._pageRequestManager = Sys.WebForms.PageRequestManager.getInstance();
            if (this._pageRequestManager) {
                this._partialUpdateBeginRequestHandler = Function.createDelegate(this, this._partialUpdateBeginRequest);
                this._pageRequestManager.add_beginRequest(this._partialUpdateBeginRequestHandler);
                this._partialUpdateEndRequestHandler = Function.createDelegate(this, this._partialUpdateEndRequest);
                this._pageRequestManager.add_endRequest(this._partialUpdateEndRequestHandler);
            }
        }
    },

    _partialUpdateBeginRequest : function(sender, beginRequestEventArgs) {
        /// <summary>
        /// Method that will be called when a partial update (via an UpdatePanel) begins,
        /// if registerPartialUpdateEvents() has been called.
        /// </summary>
        /// <param name="sender" type="Object">
        /// Sender
        /// </param>
        /// <param name="beginRequestEventArgs" type="Sys.WebForms.BeginRequestEventArgs">
        /// Event arguments
        /// </param>

        // Nothing done here; override this method in a child class
    },
    
    _partialUpdateEndRequest : function(sender, endRequestEventArgs) {
        /// <summary>
        /// Method that will be called when a partial update (via an UpdatePanel) finishes,
        /// if registerPartialUpdateEvents() has been called.
        /// </summary>
        /// <param name="sender" type="Object">
        /// Sender
        /// </param>
        /// <param name="endRequestEventArgs" type="Sys.WebForms.EndRequestEventArgs">
        /// Event arguments
        /// </param>

        // Nothing done here; override this method in a child class
    }
}
Telerik.Web.BehaviorBase.registerClass('Telerik.Web.BehaviorBase', Sys.UI.Behavior);

/* END Telerik.Web.UI.Common.Popup.BehaviorBase.js */
/* START Telerik.Web.UI.Common.Popup.PopupBehavior.js */
// JScript File

// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Permissive License.
// See http://www.microsoft.com/resources/sharedsource/licensingbasics/sharedsourcelicenses.mspx.
// All other rights reserved.
Type.registerNamespace('Telerik.Web');

Telerik.Web.PositioningMode = function() {
    throw Error.invalidOperation();
}
Telerik.Web.PositioningMode.prototype = {
    Absolute: 0,
    Center: 1,
    BottomLeft: 2,
    BottomRight: 3,
    TopLeft: 4,
    TopRight: 5
}

Telerik.Web.PositioningMode.registerEnum('Telerik.Web.PositioningMode');

Telerik.Web.PopupBehavior = function(element) {
    /// <param name="element">The DOM element the behavior is associated with.</param>
    Telerik.Web.PopupBehavior.initializeBase(this, [element]);

    this._x = 0;
    this._y = 0;
    this._positioningMode = Telerik.Web.PositioningMode.Absolute;
    this._parentElement = null;
    this._parentElementID = null;
    this._moveHandler = null;
    this._firstPopup = true;    
    this._originalParent = null;
    this._overlay = false;
    this._keepInScreenBounds = true;
    
    // This is only used by the RadSlidingPane, as its popupElement is never hidden with visibility:hidden or displya:none
    // for performance reasons.
    this._manageVisibility = true;
}

Telerik.Web.PopupBehavior._ie6pinnedList = {};


Telerik.Web.PopupBehavior.prototype = {
    
    getPageOffset : function()
    {
        var bounds = 
        {
            x : (document.documentElement.scrollLeft || document.body.scrollLeft),
            y : (document.documentElement.scrollTop || document.body.scrollTop)
        };
        return bounds;
    },

    pin : function(toPin)
    {		
        var element = this.get_element();
        var scrolls = this.getPageOffset();
                		    		    
        if ($telerik.isIE6)
        {        
            var id = this.get_id();
                            
            if (toPin)
            {        
                if (Telerik.Web.PopupBehavior._ie6pinnedList[id]) return;
                        
                var bounds = $telerik.getBounds(element);  
                                                 
                Telerik.Web.PopupBehavior._ie6pinnedList[id] = window.setInterval(Function.createDelegate(this, function()
                {                                                
                   var curScrolls = this.getPageOffset();                                        
                   var x = bounds.x - scrolls.x + curScrolls.x;
                   var y = bounds.y - scrolls.y + curScrolls.y;
                          
                   //Set the parent to be the documentElement in order to work
                   var elem = this.get_parentElement();
                   this.set_parentElement(document.documentElement);
                   
                   this.set_x(x);
                   this.set_y(y);
                                  
                   this.show();
                   
                   //Restore original parent
                   this.set_parentElement(elem);  
                }), 130);
                
            }
            else
            {   
                var timeout = Telerik.Web.PopupBehavior._ie6pinnedList[id];
                if (timeout)         
                {
                    window.clearInterval(timeout);
                }
                delete Telerik.Web.PopupBehavior._ie6pinnedList[id];
            }
        }
        else
        {               
            var next = toPin ? "fixed" : "absolute";        
            if (element.style.position == next) return;
            
            //Else if position is fixed and there is offset from top/left, it needs to be recalculated and repositioned taking offset into account
            var bounds = $telerik.getBounds(element);  
            
            //If there is scroll offset from the page, the element needs to be repositioned when setting it to be fixed.
            //Element must be positioned and made visible BEFORE setting the position to fixed        
            //Also, calling set_y() or show() causes a nasty flicker in FireFox, this is why we need to set it directly
            //TODO: We are not taking into consideration the this._positioningMode - refactor the switch statement out of show() method, and call it here and there as well
            if (toPin && (scrolls.x || scrolls.y))
            {            
                this._x = bounds.x - scrolls.x;
                this._y = bounds.y - scrolls.y;                        
                $telerik.setLocation(element, { x:this._x, y:this._y });    
            }                                                                   
            
            element.style.position = next;           
        }
    },

    //NEW - to be used in RadWindow and possibly RadDock
    center : function()
    {
       var element = this.get_element();
       if(this._manageVisibility)
       {
            $telerik.setVisible(element, true);
       }
       
       var screenBounds =  $telerik.getClientBounds();
       var elementBounds = $telerik.getBounds(element);          
       var x = parseInt((screenBounds.width - elementBounds.width) / 2);
       var y = parseInt((screenBounds.height - elementBounds.height) / 2);
       
       //Set the parent to be the documentElement in order for the center to work
       var elem = this.get_parentElement();
       this.set_parentElement(document.documentElement);
       
       this.set_x(x);
       this.set_y(y);
       
       //setLocation will not take care of offset, but the show method will.
       //Sys.UI.DomElement.setLocation(element, x,y);
       this.show();
       
       //Restore original parent
       this.set_parentElement(elem);
    },

    
    get_parentElement : function() {
        /// <value>Parent dom element.</value>        
        if (!this._parentElement && this._parentElementID) {
            this.set_parentElement($get(this._parentElementID));
            Sys.Debug.assert(this._parentElement != null, String.format('Couldn\'t find parent element "{0}"', this._parentElementID));
        }        
        return this._parentElement;
    },    
    set_parentElement : function(element) {
        this._parentElement = element;
    },
    
    get_parentElementID : function() {
        /// <value>Parent dom element.</value>
        if (this._parentElement) return this._parentElement.id
        return this._parentElementID;
    },
    set_parentElementID : function(elementID) {
        this._parentElementID = elementID;
        if (this.get_isInitialized()) {
            this.set_parentElement($get(elementID));
        }
    },
        
    get_positioningMode : function() {
        /// <value type="Telerik.Web.PositioningMode">Positioning mode.</value>
        return this._positioningMode;
    },
    set_positioningMode : function(mode) {
        this._positioningMode = mode;
    },
    
    get_x : function() {
        /// <value type="Number">X coordinate.</value>
        return this._x;
    },
    set_x : function(value) {
        if (value != this._x) {
            this._x = value;
            if ($telerik.getVisible(this.get_element()) && this._manageVisibility) {
                this.show();
            }
        }
    },
    
    get_y : function() {
        /// <value type="Number">Y coordinate.</value>
        return this._y;
    },
    set_y : function(value) {
        if (value != this._y) {
            this._y = value;
            if ($telerik.getVisible(this.get_element()) && this._manageVisibility) {
                this.show();
            }
        }
    },   
    
    get_overlay : function() {
        /// <value type="Boolean">Create an overlay.</value>
        return this._overlay;
    },    
    set_overlay : function(value) {
        this._overlay = value;
            
        //Detach the handlers, in case these are already attached.
        this._attachWindowHandlers(false);
        
        //Handle the resize and scroll events of the window to set the new position for the overlay in FF.
        if(this._overlay)
        {
            this._attachWindowHandlers(true);
        }
        else if (!((Sys.Browser.agent === Sys.Browser.InternetExplorer) && (Sys.Browser.version < 7)))
        {
            //In case the IFRAME has been created, hide it.
            var elt = this.get_element();
            var childFrame = elt._hideWindowedElementsIFrame;
            if (childFrame) {
                childFrame.style.display = "none";                
            }
        }
    }, 
    
    get_manageVisibility : function() {
        /// <value type="Boolean">Manage the visibility of the popup element.</value>
        return this._manageVisibility;
    },    
    set_manageVisibility : function(value) {
        this._manageVisibility = value;
    },
    
    get_keepInScreenBounds : function() {
        /// <value type="Boolean">Show the element in the visible viewport of the browser.</value>
        return this._keepInScreenBounds;
    },    
    set_keepInScreenBounds : function(value) {
        this._keepInScreenBounds = value;
    },

    hide : function() {
        var elt = this.get_element();
        if(this._manageVisibility)
        {
            $telerik.setVisible(elt, false);
        }
        
        if (elt.originalWidth) {
            elt.style.width = elt.originalWidth + "px";
            elt.originalWidth = null;
        }
        if (Sys.Browser.agent === Sys.Browser.InternetExplorer || this._overlay) {
            var childFrame = elt._hideWindowedElementsIFrame;
            if (childFrame) {
                childFrame.style.display = "none";                
            }
        }
    },    
    
    show : function() {                
        var elt = this.get_element();
        
        //Set current top offset, or else the page scrolls down in Mozilla - in the case when scrolling is disabled
        //This was needed in scenarios where a window is modal (as the modality would disable page scrolling)
        //However, due to other problems in Mozilla with modality & disabled scrolling - e.g. a nasty flicker in some scenarios
        //The current modal implementation does not remove scrollbars. SO this code here is not needed
        //And it will be commented because it cause a short flicker when finishing a radwindow resize operation.
        //if (Sys.Browser.agent == Sys.Browser.Firefox)
        //{
            //var bounds = this._getViewportBounds();        
            //elt.style.top = bounds.scrollTop + "px";
        //}
        
         
        //Modification of code above: If firefox and document scrolling is disabled, then showing a popup/dropdown causes the page to jump                
        if ($telerik.isFirefox)
        {
            var doc = document.documentElement;        
            var overflow =  $telerik.getCurrentStyle(doc, 'overflow');
            if ("hidden" == overflow)
            {             
                elt.style.left =  doc.scrollLeft + "px";
                elt.style.top =  doc.scrollLeft + "px";                                     
            }
        }
        
        if(this._manageVisibility)
        {
            $telerik.setVisible(elt, true);
        }
        
        // offsetParent (doc element if absolutely positioned or no offsetparent available)
        var offsetParent = elt.offsetParent || document.documentElement;

        // diff = difference in position between element's offsetParent and the element we will attach popup to.
        // this is basically so we can position the popup in the right spot even though it may not be absolutely positioned
        var diff;
        var parentBounds;
        if(this._parentElement) {
            // we will be positioning the element against the assigned parent
			//ORIGINAL TOOLKIT SCRIPT CHANGE:
			//CommonScripts.getBounds did not return proper bounds when in quirks mode:
            parentBounds = $telerik.getBounds(this._parentElement);
            
            //TEKI: Now getBounds DOES return proper offset, so this code causes problems in Quirksmode!
            //There are a lot of people who want to use the tooltip in DNN, so we need to take care of quirksmode properly!            
            //var offsetParentLocation = $telerik.getLocation(offsetParent);
            //diff = {x: parentBounds.x - offsetParentLocation.x, y:parentBounds.y - offsetParentLocation.y};            
            diff = {x: parentBounds.x, y:parentBounds.y};                             
        }
        else {
            // we will be positioning the element against the offset parent by default, since no parent element given
			//ORIGINAL TOOLKIT SCRIPT CHANGE:
			//CommonScripts.getBounds did not return proper bounds when in quirks mode:
            parentBounds = $telerik.getBounds(offsetParent);            
            diff = {x:0, y:0};
        }

        // width/height of the element, needed for calculations that involve width like centering
        var width = elt.offsetWidth - (elt.clientLeft ? elt.clientLeft * 2 : 0);
        var height = elt.offsetHeight - (elt.clientTop ? elt.clientTop * 2 : 0);
        
        var position;
        switch (this._positioningMode) {
            case Telerik.Web.PositioningMode.Center:
                position = {
                    x: Math.round(parentBounds.width / 2 - width / 2),
                    y: Math.round(parentBounds.height / 2 - height / 2)
                };
                break;
            case Telerik.Web.PositioningMode.BottomLeft:
                position = {
                    x: 0,
                    y: parentBounds.height
                };
                break;
            case Telerik.Web.PositioningMode.BottomRight:
                position = {
                    x: parentBounds.width - width,
                    y: parentBounds.height
                };
                break;
            case Telerik.Web.PositioningMode.TopLeft:
                position = {
                    x: 0,
                    y: -elt.offsetHeight
                };
                break;
            case Telerik.Web.PositioningMode.TopRight:
                position = {
                    x: parentBounds.width - width,
                    y: -elt.offsetHeight
                };
                break;
            default:
                position = {x: 0, y: 0};
        }
        position.x += this._x + diff.x;
        position.y += this._y + diff.y;
        
        $telerik.setLocation(elt, position);
       
        if(this._firstPopup) {
            // 23098: Setting the width causes the element to grow by border+passing every time. But not setting it
            // causes strange behavior in safari. Just set it once.
            elt.style.width = width + "px";
        }
        this._firstPopup = false;

        var newPosition = $telerik.getBounds(elt);        
        var boundsCheck = this._getViewportBounds();
        
        if(this._keepInScreenBounds)
        {
            var updateNeeded = false;
            
            var documentWidth = self.innerWidth ? self.innerWidth : document.documentElement.clientWidth;
            // CONSIDER: Create a generic function to return this information.
            if (!documentWidth) {
                documentWidth = document.body.clientWidth;
            }
            //Take into account the value of scrollLeft - solves problems in case the elm is not in the visible viewport
            //initially. 
            if (newPosition.x + newPosition.width - boundsCheck.scrollLeft > documentWidth ) {//- 5
                position.x -= newPosition.x + newPosition.width - documentWidth + boundsCheck.scrollLeft;//5 + 
                updateNeeded = true;
            }
            if (newPosition.x < 0) {
                position.x -= newPosition.x;
                updateNeeded = true;
            }
            if (newPosition.y < 0) {
                position.y -= newPosition.y;
                updateNeeded = true;
            }
            
            //Take into account the value of scrollTop - solves problems in case the elm is not in the visible viewport
            //initially. 
            if (boundsCheck.height < newPosition.y + newPosition.height - boundsCheck.scrollTop)
            {
                //the default popup does not check its vertical bounds
                //this check should help if the popup is near the bottom of the viewport
                if (boundsCheck.height - newPosition.height >0)
                {
                    position.y = boundsCheck.height - newPosition.height + boundsCheck.scrollTop;
                    updateNeeded = true;
                }
            }

            if (updateNeeded) {
                $telerik.setLocation(elt, position);
                
                //Update the variable that holds the position for the IFRAME that will be created (for IE6).
                newPosition = $telerik.getBounds(elt);
            }
        }
        
        elt.zIndex = 1000;

        if (((Sys.Browser.agent === Sys.Browser.InternetExplorer) && (Sys.Browser.version < 7)) || this._overlay) {
            var childFrame = elt._hideWindowedElementsIFrame;
            if (!childFrame) {
                childFrame = document.createElement("iframe");
                childFrame.src = "javascript:'<html></html>';";
                childFrame.style.position = "absolute";
                childFrame.style.display = "none";
                childFrame.scrolling = "no";
                childFrame.frameBorder = "0";
                childFrame.tabIndex = "-1";
                childFrame.style.filter = "progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)";
                //Similar insertion code is called in _onMove, but it causes "loading..." progress bar to show in the FireFox status bar
                //So it is commented there. IN theory this can be a problem if the get_element() is moved in the DOM.
                elt.parentNode.insertBefore(childFrame, elt);
                
                elt._hideWindowedElementsIFrame = childFrame;
                this._moveHandler = Function.createDelegate(this, this._onMove);
                Sys.UI.DomEvent.addHandler(elt, "move", this._moveHandler);
            }

            $telerik.setBounds(childFrame, newPosition);
            //We need to use fixed position for the ovelay in FF, so that it hides flash and media objects.
            if(Sys.Browser.agent === Sys.Browser.Firefox)
            {
                //Fixed position supports left and top, always relative to the visible viewport. That is why in case you scroll
                //down the page, the top of the ovelay should become negative.
                childFrame.style.top = parseInt(newPosition.y) - boundsCheck.scrollTop + "px";
                childFrame.style.left = parseInt(newPosition.x) - boundsCheck.scrollLeft + "px";
                childFrame.style.position = "fixed";
            }
            
            //TEKI: When in IE6 and the doctype is not XHTML this line causes the browser to freeze. No workaround was found - 
            //neither timeouts, neither modifying frame property, nor anything. The only solution is to not show the iframe          
            if ($telerik.quirksMode) return;
            
            childFrame.style.display = elt.style.display;
                                                
            if (elt.currentStyle && elt.currentStyle.zIndex)
            {
                childFrame.style.zIndex = elt.currentStyle.zIndex;
            }
            else if (elt.style.zIndex)
            {
                childFrame.style.zIndex = elt.style.zIndex;
            }
        }
    },
    
     _getViewportBounds : function()
     {
        //Get browser bounds
        var bounds = $telerik.getClientBounds();
        
        //Add scroll information for those that need it
        var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft;
        var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
        bounds.scrollLeft = scrollLeft;
        bounds.scrollTop = scrollTop;
        
        return bounds;
     },
     
    _setCoordinates : function(x, y) 
    {
        var areCoordinatesUpdated = false;
        
        if (x != this._x)
        {
            this._x = x;
            areCoordinatesUpdated = true;
        }
        if(y != this._y)
        {
            this._y = y;
            areCoordinatesUpdated = true;
        }
        if ($telerik.getVisible(this.get_element()) && areCoordinatesUpdated && this._manageVisibility) {
            this.show();
        }
    },

    
    initialize : function() {
        Telerik.Web.PopupBehavior.callBaseMethod(this, 'initialize');
        this.hide();
        this.get_element().style.position = "absolute";
    },
    
    dispose : function() {  
        var elt = this.get_element();
        if (elt) {
            //Remove handlers.
            if (this._moveHandler) {
                Sys.UI.DomEvent.removeHandler(elt, "move", this._moveHandler);
                this._moveHandler = null;
            }
            this._attachWindowHandlers(false);
            
            if ($telerik.getVisible(elt) && this._manageVisibility) {
                this.hide();
            }
            if (this._originalParent) {
                elt.parentNode.removeChild(elt);
                this._originalParent.appendChild(elt);
                this._originalParent = null;
            }
        }
        this._parentElement = null;
        Telerik.Web.PopupBehavior.callBaseMethod(this, 'dispose');
    },
    
    _onMove : function() 
    {
        var elt = this.get_element();
        var overlayIframe = elt._hideWindowedElementsIFrame;
        if (overlayIframe) 
        {   
            //Called multiple times, not needed
            //elt.parentNode.insertBefore(elt._hideWindowedElementsIFrame, elt);
            if(Sys.Browser.agent === Sys.Browser.Firefox) 
            {
                var boundsCheck = this._getViewportBounds();
                overlayIframe.style.top = parseInt(elt.style.top) - boundsCheck.scrollTop + "px";
                overlayIframe.style.left = parseInt(elt.style.left) - boundsCheck.scrollLeft + "px";
                overlayIframe.style.position = "fixed";
            }
            else
            {
                overlayIframe.style.top = elt.style.top;
                overlayIframe.style.left = elt.style.left;           
            }            
        }
    },
    
    _handleElementResize : function()
    {
        var elt = this.get_element();
        var overlayIframe = elt._hideWindowedElementsIFrame;
        if (overlayIframe) 
        {
            var newBounds = $telerik.getBounds(elt);
            $telerik.setBounds(overlayIframe, newBounds);
        }
    },
    
    _attachWindowHandlers : function(attachEvent)
    {
        if(! Sys.Browser.agent === Sys.Browser.Firefox) return;
        
        var targetElement = window;
        
        if (true == attachEvent)
        {            
            this._windowResizeDelegate = Function.createDelegate(this, this._onMove);                                
            $addHandler(targetElement, 'resize', this._windowResizeDelegate);  
            
            this._windowScrollDelegate = Function.createDelegate(this, this._onMove);   
            $addHandler(targetElement, 'scroll', this._windowScrollDelegate);                          
         }
         else
         {                          
            if (this._windowResizeDelegate) $removeHandler(targetElement, 'resize', this._windowResizeDelegate);                                   
            this._windowResizeDelegate = null;
            
            if (this._windowScrollDelegate) $removeHandler(targetElement, 'scroll', this._windowScrollDelegate);                                   
            this._windowScrollDelegate = null;
         }    
    }

}
//Telerik.Web.PopupBehavior.descriptor = {
//    properties: [   {name: 'parentElement', attributes: [ Sys.Attributes.Element, true ] },
//                    {name: 'positioningMode', type: Telerik.Web.PositioningMode},
//                    {name: 'x', type: Number},
//                    {name: 'y', type: Number} ],
//    events: [   {name: 'show'},
//                {name: 'hide'} ]
//}
Telerik.Web.PopupBehavior.registerClass('Telerik.Web.PopupBehavior', Telerik.Web.BehaviorBase);//AjaxControlToolkit.BehaviorBase);




/* END Telerik.Web.UI.Common.Popup.PopupBehavior.js */
/* START Telerik.Web.UI.Common.Popup.ModalExtender.js */
Type.registerNamespace('Telerik.Web');
Type.registerNamespace('Telerik.Web.UI'); 

Telerik.Web.UI.ModalExtender = function(flElement)
{     
    /// <summary>
    /// Implements modality functionality for an element.   
    /// </summary>               
    this._windowResizeDelegate = null;
    this._windowScrollDelegate = null;   
    
    this._xCoordinate = -1;
    this._yCoordinate = -1;
    this._backgroundElement = null;
    this._foregroundElement = flElement;
                    
    this._saveTabIndexes = new Array();
    this._saveDesableSelect = new Array();
    this._tagWithTabIndex = new Array('A','AREA','BUTTON','INPUT','OBJECT','SELECT','TEXTAREA','IFRAME');        
}

Telerik.Web.UI.ModalExtender.prototype = {    
            
    dispose : function()
    {
       /// <summary>
       /// Detaches and disposes eventhandlers       
       this.hide();
       this._backgroundElement = null;
       this._foregroundElement = null;
    },
     
    show : function()
    {
        this._attachWindowHandlers(true);    
        //Append the modal overlay
        var elem = this._getModalOverlay();        
        this._foregroundElement.parentNode.appendChild(elem);
        
        //Set z-Index        
        elem.style.zIndex = $telerik.getCurrentStyle(this._foregroundElement, 'zIndex', this._foregroundElement.style.zIndex) - 1;// + 1;                
        
        //Make the overlay visible
        elem.style.display = '';                        
        
        //Disable TAB
        this._disableTab();
        
//Disable page scrolling        
//Disabling scrolling in Mozilla, causes page to jump. When jumping is compensated, it causes the page to flicker - which is not fixable             
//        this._storeBrowserPosition();        
//        this._enableScroll(false);//MOZ problem - disabling scrolling causes the page to scroll to top
//        this._restoreBrowserPosition();

        //Calculate the overlay size
        this._updatePageLayout();
        // On pages that don't need scrollbars, Firefox and Safari act like
        // one or both are present the first time the layout code runs which
        // obviously leads to display issues - run the layout code a second
        // time to work around this problem
        this._updatePageLayout();
    },
    
    _storeBrowserPosition : function()
    {	    
	    var oBody = document.body;
	    var oDoc = document.documentElement;	
	    this._browserTop  = oBody.scrollTop > oDoc.scrollTop ? oBody.scrollTop  : oDoc.scrollTop;	
	    this._browserLeft = oBody.scrollLeft > oDoc.scrollLeft ? oBody.scrollTop : oDoc.scrollLeft;	
    },

    _restoreBrowserPosition : function(left, top)
    {
	    try
	    {
	        if (null == left) left = this._browserLeft;
	        if (null == top) top = this._browserTop;
	        
		    var oBody = document.body;
		    var oDoc = document.documentElement;		    
		    oBody.scrollTop = top;
		    oBody.scrollLeft = left;
		    oDoc.scrollTop  = top;
		    oDoc.scrollLeft = left;
	    }
	    catch(ex){};
    },
    
    hide : function()
    {                
        this._backgroundElement.style.display = 'none';        
        this._restoreTab();
//Disabling scrolling in Mozilla, causes page to jump. When jumping is compensated, it causes the page to flicker - which is not fixable     
//        this._enableScroll(true);
        this._attachWindowHandlers(false);
    },     
        
    _enableScroll : function(enable)
    {    
        if (enable)
	    {		        
		    document.body.style.overflow = null != this._overflow ? this._overflow : '';		    
		    document.documentElement.style.overflow = null != this._documentOverflow ? this._documentOverflow : '';
		    
		    document.body.style.marginRight = '';
	    }
	    else
	    {		
	        this._overflow = document.body.style.overflow;	        	        	        
		    document.body.style.overflow = 'hidden';
		    
		    this._documentOverflow = document.documentElement.style.overflow;
		    document.documentElement.style.overflow = 'hidden';
		    
		    //!TODO: Better implementation to prevent the scroller from shaking the page when being hidden 
		    document.body.style.marginRight = '18px';		    
	    }
    },
    
    _getModalOverlay : function()
    {
        if (!this._backgroundElement)
        {
            var div = document.createElement('div');
            div.style.display = 'none';
            div.style.position = 'absolute';
            div.style.left = '0px';
            div.style.top = '0px';        
            div.style.zIndex = 10000;            
            div.style.backgroundColor = "#aaaaaa";
            div.style.filter = "progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=50)";
            div.style.opacity = ".5";
            div.style.mozOpacity = ".5";
            
            //Classname should be set to allow for devs to output it on the page, and style the DIV
            div.className = "TelerikModalOverlay";
                                    			
            
            this._backgroundElement = div;
        }
        return this._backgroundElement;                
    },
                                        
    _attachWindowHandlers : function(attachEvent)
    {
        var targetElement = window;//document;
        
        if (true == attachEvent)
        {            
            this._windowResizeDelegate = Function.createDelegate(this, this._updatePageLayout);                                
            $addHandler(targetElement, 'resize', this._windowResizeDelegate);  
            
            this._windowScrollDelegate = Function.createDelegate(this, this._updatePageLayout);                                
            $addHandler(targetElement, 'scroll', this._windowScrollDelegate);                          
         }
         else
         {                          
            if (this._windowResizeDelegate) $removeHandler(targetElement, 'resize', this._windowResizeDelegate);                                   
            this._windowResizeDelegate = null;
            
            if (this._windowScrollDelegate) $removeHandler(targetElement, 'scroll', this._windowScrollDelegate);                                   
            this._windowScrollDelegate = null;
         }    
    }, 
                               
    _updatePageLayout : function() {
        
        ///Make the overlay div as big as the page        
        var scrollLeft = (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft);
        var scrollTop = (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop);
        var clientBounds = $telerik.getClientBounds();
        var clientWidth = clientBounds.width;
        var clientHeight = clientBounds.height;
        
        var elem = this._getModalOverlay();        
        elem.style.width = Math.max(Math.max(document.documentElement.scrollWidth, document.body.scrollWidth), clientWidth)+'px';
        elem.style.height = Math.max(Math.max(document.documentElement.scrollHeight, document.body.scrollHeight), clientHeight)+'px';            
    },
    
     _disableTab : function() {        
        /// Change the tab indices so we only tab through the modal popup
        /// (and hide SELECT tags in IE6)
        
        var i = 0;
        var tagElements;
        var tagElementsInPopUp = new Array();
        Array.clear(this._saveTabIndexes);

        //Save all popup's tag in tagElementsInPopUp
        for (var j = 0; j < this._tagWithTabIndex.length; j++) {
            tagElements = this._foregroundElement.getElementsByTagName(this._tagWithTabIndex[j]);
            for (var k = 0 ; k < tagElements.length; k++) {
                tagElementsInPopUp[i] = tagElements[k];
                i++;
            }
        }

        i = 0;
        for (var j = 0; j < this._tagWithTabIndex.length; j++) {
            tagElements = document.getElementsByTagName(this._tagWithTabIndex[j]);
            for (var k = 0 ; k < tagElements.length; k++) {
                if (Array.indexOf(tagElementsInPopUp, tagElements[k]) == -1)  {
                    this._saveTabIndexes[i] = {tag: tagElements[k], index: tagElements[k].tabIndex};
                    tagElements[k].tabIndex="-1";
                    i++;
                }
            }
        }

        //IE6 Bug with SELECT element always showing up on top
        i = 0;
        if ((Sys.Browser.agent === Sys.Browser.InternetExplorer) && (Sys.Browser.version < 7)) {
            //Save SELECT in PopUp
            var tagSelectInPopUp = new Array();
            for (var j = 0; j < this._tagWithTabIndex.length; j++) {
                tagElements = this._foregroundElement.getElementsByTagName('SELECT');
                for (var k = 0 ; k < tagElements.length; k++) {
                    tagSelectInPopUp[i] = tagElements[k];
                    i++;
                }
            }

            i = 0;
            Array.clear(this._saveDesableSelect);
            tagElements = document.getElementsByTagName('SELECT');
            for (var k = 0 ; k < tagElements.length; k++) {
                if (Array.indexOf(tagSelectInPopUp, tagElements[k]) == -1)  {
                    this._saveDesableSelect[i] = {tag: tagElements[k], visib: $telerik.getCurrentStyle(tagElements[k], 'visibility')} ;
                    tagElements[k].style.visibility = 'hidden';
                    i++;
                }
            }
        }
    },

    _restoreTab : function() {        
        /// Restore the tab indices so we tab through the page like normal
        /// (and restore SELECT tags in IE6)        

        for (var i = 0; i < this._saveTabIndexes.length; i++) {
            this._saveTabIndexes[i].tag.tabIndex = this._saveTabIndexes[i].index;
        }

        //IE6 Bug with SELECT element always showing up on top
        if ((Sys.Browser.agent === Sys.Browser.InternetExplorer) && (Sys.Browser.version < 7)) {
            for (var k = 0 ; k < this._saveDesableSelect.length; k++) {
                this._saveDesableSelect[k].tag.style.visibility = this._saveDesableSelect[k].visib;
            }
        }
    }
};

Telerik.Web.UI.ModalExtender.registerClass('Telerik.Web.UI.ModalExtender', null);
/* END Telerik.Web.UI.Common.Popup.ModalExtender.js */
/* START Telerik.Web.UI.ToolTip.RadToolTip.js */
//Class that manages tooltips.
//- singleton
//- regiter global event handlers
//- log a tooltip for being shown
//- hide currently visible tooltip
Type.registerNamespace('Telerik.Web.UI');

Telerik.Web.UI.RadToolTipControllerClass = function() 
{                 
    /// <exclude/>       
    //Current tentative tooltip
    this._tooltipToShow = null;
    
    //Current visible tooltip
    this._activeToolTip = null;            
    
    //Attach body event handlers 
    this._registerGlobalBodyEventHandlers();    
}

Telerik.Web.UI.RadToolTipControllerClass.prototype = 
{            
     _registerGlobalBodyEventHandlers : function()
    {     
        //Register a single keydown handler for the body to handle ESC
           
        //ESC handler      
        var escHandler = Function.createDelegate(this, function(e)
        {                    
            if (e.keyCode == 27)//Escape will close the tooltip only if it is not modal
            {                    
                if (this._activeToolTip && !this._activeToolTip.isModal())
                {
                    this._hideCurrentToolTipUnconditionally();
                }
            }
        });
                
        $addHandler(document.body, 'keydown', escHandler);
        
        //Click handler            
        var clickHandler = Function.createDelegate(this, function(e) 
        {                        
            this._hideOnBodyClick(e);            
        });
                      
        $addHandler(document.body, 'click', clickHandler);
                                            
        //Dispose the globale event handlers
        Sys.Application.add_unload(function()
        {                               
            $removeHandler(document.body, 'keydown', escHandler);
            $removeHandler(document.body, 'click', clickHandler);
        });                     
    },
    
    //NEW: Modified method to not hide a modal tooltip!
    _hideOnBodyClick : function(e)
    {  
        // <exclude/>   
        var wasHidden = false;   
        if (this._activeToolTip != null && !this._activeToolTip.isModal())
        {   
           //We need to check whether the element that initiated the click is a child of the tooltip           
           var tooltip = this._activeToolTip;           
           if (tooltip._isMouseOverElement(e, tooltip._tableElement)) return;
           //Else make a request ot the tooltip to hide   
           wasHidden = this._activeToolTip.hide(true);
        }
        
        if (wasHidden) this._activeToolTip = null;
    },
    
    _cancelLastShowRequest : function()
    {
        /// <exclude/>
        //if there was another tooltip waiting to be shown - cancel its request
        if (this._tooltipToShow)
        {
            //Just in case - use a local variable to avoid potential recursion!
            var tooltip = this._tooltipToShow;
            
            this._tooltipToShow = null;
                        
            tooltip.cancelShowDelay();
        }        
    },
    
     //Forces hide to currently visible tooltip
    _hideCurrentToolTipUnconditionally : function()
    {    
        /// <exclude/>
        //The following scenario is possible
        //User initiates tooltip show, then showdelay kicks in, then before it is over, user clicks to discard tooltip from showing
        this._cancelLastShowRequest();
       
        if (this._activeToolTip != null)
        {                  
          this._activeToolTip.hide();
        }
        this._activeToolTip = null;
    },
    
                        
    //STEP 1
    requestShow : function(newToolTip)
    {
        /// <exclude/>
        this._cancelLastShowRequest();        
        this._tooltipToShow = newToolTip;        
    },
    
    //STEP 1.5 - Cancel a request only if the same tooltip initiated it - called from RadToolTip
    cancelSpecificShowRequest : function (tooltip)
    {       
        /// <exclude/> 
        if (this._tooltipToShow == tooltip)
        {
            this._cancelLastShowRequest();
        }
    },
        
    //STEP 2
    showTooltip : function(newToolTip)
    {
        /// <exclude/>
        if (!newToolTip || newToolTip.isVisible()) return;
        
        //cancel if a tooltip is waiting to be shown
        this._cancelLastShowRequest();
        
        //hide current tooltip
        this.set_activeToolTip(newToolTip);
                
        //show the tooltip and mark it as current tooltip        
        newToolTip.show();
    },

    //STEP 3                    
    notifyToolTipClosed : function(newToolTip)
    {
        /// <exclude/>
        if (this._activeToolTip == newToolTip)
        {
            this._activeToolTip = null;
        }
    },
    
    
    set_activeToolTip : function(newToolTip)
    {     
        /// <exclude/>       
        if (newToolTip != this._activeToolTip)
        {
            this._hideCurrentToolTipUnconditionally();
        }
        this._activeToolTip = newToolTip;
    },
    
    get_activeToolTip : function()
    {
        return   this._activeToolTip;
    }, 
    
    //Return a reference to the controller - the method name follows the MS AJAX convention - e.g. Sys.WebForms.PageRequestManager.getInstance();
    getInstance : function()
    {        
        /// <exclude/>
        return this;
    }                         
}   

Telerik.Web.UI.RadToolTipControllerClass.registerClass('Telerik.Web.UI.RadToolTipControllerClass', null); 

//Create a singleton
if (!Telerik.Web.UI.RadToolTipController)
{
    Telerik.Web.UI.RadToolTipController = new Telerik.Web.UI.RadToolTipControllerClass();    
}
//====================================================================================================================//

Type.registerNamespace('Telerik.Web.UI');

Telerik.Web.UI.RadToolTip = function(element) {
    /// <summary>
    /// The ToolTip control implements a rich UI tooltip for a HTML target element
    /// </summary>
    /// <param name="element" type="Sys.UI.DomElement" domElement="true">
    /// DOM element associated with the behavior
    /// </param>
    Telerik.Web.UI.RadToolTip.initializeBase(this, [element]);
            
    this._offsetX = 0;
    this._offsetY = 6;
    this._position = Telerik.Web.UI.ToolTipPosition.BottomCenter;
    this._horizontalPosition = null;//cached for faster retrieval
    this._verticalPosition = null;  //cached
    this._targetControlID = null;
    this._serverTargetControlID = null;
    this._serverValue = "";
    this._formID = null;
    
    //HTML elements
    this._targetControl = null; 
    this._popupElement = null;        
    this._tableElement = null;
    this._contentCell = null;    
    this._titleElement = null;
    this._contentElement = null;
    this._calloutElement = null;
    this._closeLink = null;
    
    this._popupBehavior = null;
    this._popupVisible = false;
    this._modal = false;
    
    //Event handlers        
    this._onModalShowHandler = null;
    this._onModalCloseHandler = null;
                
    //Member variables
    this._skin = "Default";
    this._title = "";
    this._text = "";    
    this._width = "";
    this._height = "";                
                
    this._relativeTo = Telerik.Web.UI.ToolTipRelativeDisplay.Mouse;
    this._contentScrolling = Telerik.Web.UI.ToolTipScrolling.Auto;
    this._showEvent = Telerik.Web.UI.ToolTipShowEvent.OnMouseOver;
    this._visibleOnPageLoad = false;
    this._sticky = false;
    this._manualClose = false;
    this._mouseTrailing = false;    
    this._showCallout = true;
                        
    //Variables that hold the current delay for an action and are compared with the user-specified values to decide whether the action should be performed
    this._showDelayRef = null;
    this._autoCloseRef = null;
        
    this._showDelay = 300;    
    this._autoCloseDelay = 2000;        
    this._hideDelay = 100;
            
    //Animation
    this._animation = Telerik.Web.UI.ToolTipAnimation.None;
    this._tooltipAnimation = null;
    
    //NEW: zIndex implementation
    this._zIndex = 8000;
}

//"Static" method to return current tooltip
Telerik.Web.UI.RadToolTip.getCurrent = function()
{
    var controller = Telerik.Web.UI.RadToolTipController.getInstance();
    if (!controller) return null;
    return controller.get_activeToolTip();    
}


Telerik.Web.UI.RadToolTip.prototype = {

    //NEW - called by RadToolTipManager
    get_zIndex : function() 
    {
        /// <exclude />             
        return this._zIndex;
    },
    
    set_zIndex : function(value) 
    {          
        var zIndex = parseInt(value);        
        if (isNaN(value)) return;
        
        /// <exclude />             
        if (this._zIndex != value) { 
            this._zIndex = value;            
        }
    },
    
    //###########---------------- PUBLIC API ---------------------##################//                 
    initialize : function() 
    {      
        /// <exclude />
        Telerik.Web.UI.RadToolTip.callBaseMethod(this, 'initialize');
        
        //Force set_position to cache the horizontal and vertical enum values        
        this.set_position(this._position);
                  		    		                                          
        //if visible on page load - show
        if (this._visibleOnPageLoad)
        {        
            this.show();
        }                                                    
    },
    
    dispose : function() 
    {                    
        //If an open animation is currently going on, cancel it        
        if (this._tooltipAnimation)  this._tooltipAnimation.dispose();
    
        /// <exclude />  
        if (this._popupBehavior)
        {
            this._popupBehavior.dispose();
            this._popupBehavior = null;
        }
                
        this._registerPopupHandlers(false);                        
        this._registerMouseHandlers(this._targetControl, false);
        
        this._makeModal(false);

        //Detach event handler from the manual close element        
        if (this._closeLinkHandler && this._closeLink) 
        {           
            $removeHandler(this._closeLink, 'click', this._closeLinkHandler);
            this._closeLinkHandler = null;
        }
        
        //The content element can have all kinds of stuff that was inserted between tooltip tags declaration
        //Current implementation transfers the child elements from the root div to a new element and then inserts this element to the end of the FORM
        //When a tooltip is in update panel this content should be disposed as well to avoid problems
        //We try to do it by moving the _popupElement into the root element of the tooltip (its original div)
        //However, this code should be made sure not to disrupt the TooltipManager + OnAjaxUpdate content for multiple tooltips set in manager.                                         
        if (this._popupElement)
        {
           var thisId = this.get_id();
    	   if (thisId)
    	   {
    	        var serverElement = $get(thisId);
    	        if (serverElement)
    	        {    	        
    	            serverElement.appendChild(this._popupElement);    	            
    	        }
    	   }    	   
        }
                                                                     
        Telerik.Web.UI.RadToolTip.callBaseMethod(this, 'dispose');
    },
    
    //--------------------//
    isCreated : function()
    {
        return this._popupElement != null;
    },
        
    requestShow : function() 
    {
        /// <exclude />                                    
        this._resetShowDelay();                                                                                  
    },
    
                
    hide : function(keepIfManualClose)
    {
        /// <summary>
        /// Hides the tooltip
        /// </summary>            
        /// <param name="keepIfManualClose" type="Boolean" mayBeNull="true">
        /// If param is set to 'true', and ManualClose = true is set to the tooltip, the tooltip will remain visible
        /// </param>                                                    
        if (true==keepIfManualClose && this._manualClose)//|| this._sticky -> should not check for stickyness here. Problem when trying to close when clicking mouse outside of tooltip on the parent page.
        {
           return false;
        }
        this._hide();
        return true;
    },
    
    //clone method returns a new tooltip with same settings as current, but for a new targetElement
    clone : function(targetElement, tooltipID)
    {
       /// <summary>
       /// Creates a clone of the tooltip for another targetElement, and possibly with a different text to display.
       /// </summary>
       /// <param name="targetElement" type="Sys.UI.DomElement">
       /// The target element for which tooltip should be created
       /// </param> 
       /// <param name="tooltipID" type="String" mayBeNull="true">
       /// The id of the newly created tooltip 
       /// </param> 
        if (!targetElement) { alert("clone error: No target element specified"); return; } //TODO: Use the framework facilities to alert error
                       
       //Get the events object
       var evs = this._getEventsParameter();       
              
       //Get the properties object
       var props = this._getPropertiesParameter();      
                                            
       props["targetControlID"] = targetElement.getAttribute("id");                     
       //if no id is set, set directly the control!
       if (!props["targetControlID"])
       {
            props["targetControl"] = targetElement;
       }
       
       //if no text, this means go for AJAX style
       //if (text) props["text"] = text;//Not called anywhere with this [function] parameter, so parameter wa changed to tooltipID
    
       var span = document.createElement("SPAN")//Create an element that does not need to be inserted in the document.body
       //NEW: tooltips created by ToolTipManager with cloning should have an ID
       if (tooltipID) span.setAttribute("id", tooltipID);
                                                    
       var tooltip = $create(Telerik.Web.UI.RadToolTip, 
                             props,
                             evs, 
                             null, 
                             span
                            );               
       return tooltip;      
    },
    
    
    show : function()
    {          
       /// <summary>
       /// Displays the tooltip at the proper position, relative to its target control.
       /// </summary>
        
        //Lazy initialization - create UI before show
        this._createUI();
                
        //Throw BeforeShow event with ability to cancel
        var cancelArgs = new Sys.CancelEventArgs();
        this.raiseEvent('beforeShow', cancelArgs);                
        if (cancelArgs.get_cancel())
        {
            return;
        }
        
        //Allow a timeout when registering the handlers - fixes a problem under IE6 when Sticky is set to true.
        //Basically, this scenario causes IE6 to hang. 
        if($telerik.isIE6)
        {
            var thisRef = this; 
            window.setTimeout(function(){      
                //Attach event handlers within the popup to track mouseout.
                thisRef._registerPopupHandlers(true);    
            }, 200); 
        } 
        else
        {
            this._registerPopupHandlers(true);
        }
                                               
        //Just in case the tooltip manager is not properly informed - set this to be the current tooltip
        this._getToolTipController().set_activeToolTip(this);
         
        
        //NEW: Unpin popup before playing animation or showing to position correctly
        this._popupBehavior.pin(false); 
        
        //In some scenarios, when the tooltip is called to be shown as a result of clicking an element (button or input), the click event will propagate to the
        //tooltip controller,which will cancel the [already] started show. So, let the click be handled first by using a small timeout        
        window.setTimeout(Function.createDelegate(this, function()
        {                                   
            if (this._animation == Telerik.Web.UI.ToolTipAnimation.None)
            {
                this._show();
                //Raise event
                this._afterShow();
            }
            else
            {          
                this._playAnimation();
            }
        }), 0);
    },
    
    //Called by RadToolTipManager
    showLoadingMessage : function(toShow)
    {
        /// <exclude/>
        if (toShow)
        {
            var div = document.createElement("DIV");
            div.className = this._getFullSkinName() + " LoadingSign";
            this._contentCell.appendChild(div);
        }
        else this._contentCell.innerHTML = "";
    },
    
    isModal : function()
    {
        return this._modal;
    },

                      
    set_contentElement : function(contentElement)
    {          
       /// <summary>
       /// Sets a new content element to the tooltip 
       /// </summary>
       /// <param name="contentElement" type="Sys.UI.DomElement">
       /// The new content element to be displayed as the tooltip content
       /// </param> 
                                 
       this._contentCell.innerHTML = "";
         
       if (contentElement.parentNode && contentElement.parentNode.removeChild)
       {
           contentElement.parentNode.removeChild(contentElement);		       
       }
 		        
       this._contentCell.appendChild(contentElement);                            
       contentElement.style.display = "";//make visible
         
       //Set as content element in order to calculate overflow!
       this._contentElement = contentElement;                 
    },
    
    get_contentElement : function()
    {       
        /// <summary>
       /// Gets the content element of the tooltip 
       /// </summary>
       /// <value type="Sys.UI.DomElement">
       /// Returns a reference to the current content element of the tooltip
       /// </value>
       return this._contentElement;
    },
      
    //It is called by set_text, and it also duplicates it to some extent. Could be optimized.  
    set_content : function(text)
    {           	
       /// <summary>
       /// Sets new content to the tooltip 
       /// </summary>
       /// <param name="text" type="String">
       /// The new content to be displayed in the tooltip
       /// </param>                      
	   var textElement = document.createElement('DIV');
	   textElement.innerHTML = text;		  
	   this._text = text;
	   	   
	   if (this.isCreated())
	   {
	       //Set as content element
	       this.set_contentElement(textElement);
	   }	   	     	   
    },
    
    get_content : function()
    {
      /// <summary>
      /// Gets the current content of the tooltip 
      /// </summary>
      /// <value type="Sys.UI.DomElement">
      /// Returns the current content of the tooltip
      /// </value>
      return this._contentElement ? this._contentElement.innerHTML : "";
    },
            
    //##############------------ CONTROLLER RELATED METHODS------------------##############//
    cancelAutoCloseDelay : function()
    {
        /// <exclude/>
        //if another delay was started        
        if (this._autoCloseRef)
        {        
            window.clearTimeout(this._autoCloseRef);
            this._autoCloseRef = 0;
        }
    },
    
    
    //Called if mouse enters another tooltip before this one is shown. Called from the ToolTipManager as well!
    cancelShowDelay : function()
    {        
        /// <exclude/>
        if (this._showDelayRef)        
        {            
            window.clearTimeout(this._showDelayRef);
            this._showDelayRef = null;
        } 
        
        //Provide feedback to the ToolTipManager in the scenario where the user hovers over the mouse, 
        //but then moves out before timeout is properly executed. The tooltip should cancel its ONW show request
        this._getToolTipController().cancelSpecificShowRequest(this);
    },
    
    
    _getToolTipController : function()
    {        
        return Telerik.Web.UI.RadToolTipController.getInstance();
    },
            
    _resetAutoCloseDelay : function()    
    {
        this.cancelAutoCloseDelay();
    
        //Do not autoclose if sticky or manual close
        if (this._manualClose || this._sticky) return;
                    
        if (this._autoCloseDelay)
        {            
            var _this = this;
            this._autoCloseRef = window.setTimeout(function()
            {                
                _this.hide(true);                
                                                
            }, this._autoCloseDelay);
        }
    },
               
    _resetShowDelay : function()
    {        
        this.cancelShowDelay();
                               
        var _this = this;            
        var fnRef = function()
        {                   
           _this._getToolTipController().showTooltip(_this);           
           //cancel the delay when it is done!(actually someone else [the manager] already cancelled it)
           _this.cancelShowDelay();
        };
        this._showDelayRef = window.setTimeout(fnRef, this._showDelay);
    },
        
    _show : function()
    {                   
        //Get proper tooltip position
        var bounds = null;
        try
        {
            bounds = this.getToolTipBounds();
        }
        catch(e)
        {   
           //Can happen at the end of MS AJAX updating the targetElement that it is not added to the page yet
           var _this = this;
           window.setTimeout(function()
           {                
                _this._addToolTipToDocument();                                
            }, 10);
            return;
        };
        
        //Show the popup         
        this._setPopupVisible(bounds.x,bounds.y);
                                    
        this._resetAutoCloseDelay();
        
        //visible flag is set here, and not in _setPopupVisible as _setPopupVisible 
        //is called on two occasions as a utility method to allow for proper size calculation        
        this._popupVisible = true;                
    },
    
    _afterShow : function()
    {                                
        //Set the popup to be PINNED if needed
        this._popupBehavior.pin(this._isRelativeToBrowserWindow());
	                         		                                   
        //Raise show event here!
        this.raiseEvent('show');  
    },
                             
    _hide : function()
    {   
        //If an open animation is currently going on, cancel it - make sure this code is before next check - because sometimes animations execute a bit later and it results in incorrect behavior
        if (this._tooltipAnimation)  this._tooltipAnimation.stop();                             
        
        
        //Cancel all possible timeouts
        this.cancelShowDelay();
        this.cancelAutoCloseDelay();
                     
        var cancelArgs = new Sys.CancelEventArgs();
        this.raiseEvent('beforeHide', cancelArgs);                
        if (cancelArgs.get_cancel())
        {
            return;
        }
                                                    
        //Add onclose animation here
        if (this._tooltipAnimation)
        {
            this._tooltipAnimation.play(true);                                   
        }
        else this._afterHide();               
    },
    
   //This function is called by both animation.onEnd and by the tooltip code when there is no animation
    _afterHide : function()
    {
        try
        {
            //Possible to throw an exception in AJAX based scenarios where clickin on element fired an AJAX request as well as propagated to the body to hide the tooltip
            if (this._popupBehavior)
            {
                this._popupBehavior.hide(true);
                
                //NEW: Problem in IE6 - because of its pinning mechanism it keeps calling the timeout and uses CPU time even if tooltip is not visible   
                this._popupBehavior.pin(false);                
            }
                
        }
        catch(ex){;}
        
        this._popupVisible = false;

        //Notify controller that tooltip was hidden                                
        this._getToolTipController().notifyToolTipClosed(this);
        this.raiseEvent('hide');        
        //Detach popup body handlers
        this._registerPopupHandlers(false);
    },

    
    _isRelativeToBrowserWindow : function()
    {            
        if (!this._targetControl || this._relativeTo == Telerik.Web.UI.ToolTipRelativeDisplay.BrowserWindow)
        {
            return true;
        }        
        return false;               
    },
                  
     _playAnimation : function()
    {          
        //Common configuration for several animations
        var commonResizeAnimationConfiguration = function()
        {	                             	                                          
           var tooltip = this.controller;
                              
           //Get left and top relative to target element, then show tooltip for a moment and get absolute bounds, left and top 
           var relativeBounds = tooltip.getToolTipBounds();                   
           tooltip._setPopupVisible(relativeBounds.x, relativeBounds.y);
           var popupBounds = $telerik.getBounds(tooltip._popupElement);          

           tooltip._popupBehavior.hide();  
           
           //Configure animation end bounds
           this.set_endBounds(popupBounds);                                            
        };                                       
                         
     
        if (!this._tooltipAnimation)
        {   
            //For Resize && Slide we want to change the vertical direction of the tooltip animation if the RelativeTo = BrowserWindow
            //For Resize we want to change the horizontal direction of tooltip animation as well. Since vertical position is used by both, it is declared here
            var pos = this._position;
            var vp = this._verticalPosition;
            
            var relativeToBrowser = this._isRelativeToBrowserWindow();
            if (relativeToBrowser && this._verticalPosition != 2)//2 is middle
            {
               vp = (this._verticalPosition == 1 ? 3 : 1);//1 is top, 3 is bottom                   
               pos = parseInt(vp + "" + this._horizontalPosition);
            }  

            //Set target element
            var target = relativeToBrowser? document.documentElement : this._targetControl;
                                 
            if (this._animation == Telerik.Web.UI.ToolTipAnimation.Fade)
            {                                                	        	        	       
	            this._tooltipAnimation = new Telerik.Web.UI.Animations.FadeAnimation(this, null, null, this._popupElement,this._position, target);
	            
	            this._tooltipAnimation.onShowStart = function()
                {	                            
                   this.controller._show();               
                };
            }                           
            else if (this._animation == Telerik.Web.UI.ToolTipAnimation.FlyIn)
            {                
                this._tooltipAnimation = new Telerik.Web.UI.Animations.FlyInAnimation(this, null, null, this._popupElement, this._position, target);
	            this._tooltipAnimation.onShowStart = commonResizeAnimationConfiguration;
            }
            else if (this._animation == Telerik.Web.UI.ToolTipAnimation.Slide)
            {                                                          
                this._tooltipAnimation = new Telerik.Web.UI.Animations.SlideAnimation(this, null, null, this._popupElement, pos, target);
	            this._tooltipAnimation.onShowStart = commonResizeAnimationConfiguration;
            }
            else if (this._animation == Telerik.Web.UI.ToolTipAnimation.Resize)
            {        
                if (relativeToBrowser && this._horizontalPosition != 2)//2 is center
                {
                   var hp = (this._horizontalPosition == 1 ? 3 : 1);//1 is left, 3 is right
                   pos = parseInt(vp + "" + hp);
                } 
                
                
                this._tooltipAnimation = new Telerik.Web.UI.Animations.ResizeAnimation(this, .2, 50, this._popupElement, pos, target);	                            
                this._tooltipAnimation.onShowStart = commonResizeAnimationConfiguration;
            }
        }

        if (this._tooltipAnimation)
        {            
            //If pos is relative to browser window and animation is enabled, need to hide the X-axis scrollbar because some animations cause it to appear.        
            if (this._isRelativeToBrowserWindow())
            {
               this._documentOverflowX = document.documentElement.style.overflowX;
               document.documentElement.style.overflowX = "hidden";                
            }
                                      
            this._tooltipAnimation.onShowEnd = function()
            {	
                //Make sure another tooltip that might be visible gets hidden
                this.controller._show();   
                
                //If relative to browser window we might need to restore the scrollbars
                if (null != this.controller._documentOverflowX)
                {                
                    document.documentElement.style.overflowX = this.controller._documentOverflowX;
                    this.controller._documentOverflowX = null;
                }
                                  
                //Raise event
                this.controller._afterShow();                               
            };  

                   
            this._tooltipAnimation.onHideEnd = function()
            {	                        
                this.controller._afterHide();//!
            };    	                    
            
            this._tooltipAnimation.play();                             
        }
    },
    
    //---------------------------------------- 'Modality' implementation ---------------------------------------------//
    _makeModal : function(bModal)
    {
       //Dispose of old state, whatever it was
       if (this._onModalShowHandler)
       {
           this.remove_show(this._onModalShowHandler);
           this._onModalShowHandler = null;
       }
       
       if (this._onModalCloseHandler)
       {
            this.remove_hide(this._onModalCloseHandler);
            this._onModalCloseHandler = null;
       }
       
       if (this._modalExtender)
       { 
            this._modalExtender.dispose();
            this._modalExtender = null;
       }
       
       //Return if modality should be turned off
       if (!bModal) return;
                            
       this._onModalShowHandler = function(sender)
       {
          //Create the modal overlay here, becase it needs to be passed an existing html this._popupElement
          if (!sender._modalExtender) 
          {
            sender._modalExtender = new Telerik.Web.UI.ModalExtender(sender._popupElement);
          }
          
          //Show the modal overlay
          sender._modalExtender.show();                              
       };
       
       this.add_show(this._onModalShowHandler);
       
       this._onModalCloseHandler = function(sender)
       {
           //Hide the modal overlay
           if(sender._modalExtender) sender._modalExtender.hide(); 
       };
       this.add_hide(this._onModalCloseHandler);                     
    },        
    
    //---------------------------------------- 
                               
    _isMouseOverElement : function (e, element)
    {        
         var rect = null;
        //Can throw exception if called by body onclick eventhandler after AJAX update
        try
        {
           rect = $telerik.getBounds(element);        
        }
        catch(e)
        {
            return false;
        }
                
        if (e && e.target)
        {
            //BUG in IE6: If there is a select element in the dropdown [heavyweight object], clientX and clientY come with bad values, and the contains
            //Mozilla bug - option elements in a select cause the mouse to return incorrect mouse offsets    
            var tagName = e.target.tagName;                        
            if (tagName == "SELECT" || tagName == "OPTION") return true;
            if (e.clientX < 0 || e.clientY < 0) return true;            
        }
                                        
        //See if targetControl rect contains the mouse x,y
        var body = (document.compatMode && document.compatMode!="BackCompat")? document.documentElement : document.body;                        
        var x = e.clientX + body.scrollLeft;
        var y = e.clientY + body.scrollTop;                        
        
        //When mouse is taken out slowly  e.clientX and  e.clientY return values on the 'border' of the element - technically - still within it
        rect.x += 3;//1;
        rect.y += 2;
        rect.width -= 4;//2;
        rect.height -= 4;//2; //Moz!
        var toKeep = $telerik.containsPoint(rect, x,y);       
        //window.document.title = toKeep + " <<" + element.tagName + " =MOUSEOUT [" + x + "," + y + "]==[topleft =" + (rect.x ) + "," + (rect.y) + ", bottomright=" + (rect.x + rect.width) + "," + (rect.y + rect.height) + "]";
                
        return toKeep;
    },
              

    //##############------------ MOUSE EVENT HANDLERS ------------------##############//              
    _onMouseOver : function(e)
    {        
        /// <summary>
        /// Show the tooltip when its control is hovered
        /// </summary>
        /// <param name="e" type="Sys.UI.DomEvent" mayBeNull="true">
        /// Event info
        /// </param>
        this._logMousePosition(e);      
        
        this._resetShowDelay();
        this._getToolTipController().requestShow(this);        
                        
        if (e)
        {
            //TEKI: We do not want to cancel the onmouseover event due to scenarios involving rad menu and rad combo, for example.
            //e.stopPropagation();
        }                
    },
      
    _onMouseMove : function(e)
    {
        //if the tooltip is not visible, but is trailing the mouse, the current mouse position should be logged when showing it.
        this._logMousePosition(e);
                
        this._resetAutoCloseDelay();
            
        if (this._mouseTrailing && this.isVisible()) //if it is not visible tooltip is in the state of waiting to be shown
        {  
           this._show();
        }
    },
            
    _onMouseOut : function(e)
    {                              
      //If you are moving out of the element, you need to close it immediately, and to also cancel show delay
      var toKeep = this._isMouseOverElement(e, this._targetControl);
      if (!toKeep)
      {      
        this.cancelShowDelay();
        
        if (!this._sticky)
        {
            //There are 7 scenarios when a tooltip should hide  
            //1) when mouse leaves target element, 2)when mouse was idle (autoclose), 3) when sticky and mouse leaves tooltip itself, 4) when manual close and user hits [x]
            //5) when user clicks on body, 6) when user presses ESC, 7) when a new tooltip is about to be shown
            //Only in the scenario when the user leaves the target element [this scenario] the tooltip should apply HideDelay                                
            if (this._hideDelay > 0)
            {                   
                var _this = this;
                window.setTimeout(function()
                {                
                    _this.hide(true);                                                    
                }, this._hideDelay);
            }
            else this.hide(true);            
        }
      }
    },                
    
    
    _onClick : function(e)
    {                              
      this._onMouseOver(e);      
      //Cancel the contextmenu event
      return $telerik.cancelRawEvent(e);	      
    },             

    _onRightClick : function(e)
    {                              
      this._onMouseOver(e);
      //Cancel the contextmenu event
      return $telerik.cancelRawEvent(e);	
    },             

    //###---------------------------- UTILITY FUNCTIONS ------------------------------------#######//
    
    //Allows for registering events to multiple controls
    //Do not use $clearHandlers as it can cause a conflict when the control is attached to another control's element    
    _registerMouseHandlers : function(targetElement, attachEvent)
    {                
        if (true == attachEvent)
        {                                    
            var handlers = {};
            var showEnum = Telerik.Web.UI.ToolTipShowEvent;
            if (this._showEvent == showEnum.OnMouseOver)
            {                            
                this._onMouseOverDelegate = Function.createDelegate(this, this._onMouseOver);
                this._onMouseMoveDelegate = Function.createDelegate(this, this._onMouseMove);
                this._onMouseOutDelegate = Function.createDelegate(this, this._onMouseOut);
                $addHandler(targetElement, 'mouseover', this._onMouseOverDelegate);              
                $addHandler(targetElement, 'mousemove', this._onMouseMoveDelegate);              
                $addHandler(targetElement, 'mouseout', this._onMouseOutDelegate);              
            }
            
            if (this._showEvent == showEnum.OnClick)
            {             
                this._onClickDelegate = Function.createDelegate(this, this._onClick);
                $addHandler(targetElement, 'click', this._onClickDelegate);              
            }
            
            if (this._showEvent == showEnum.OnRightClick)
            {                
                this._onRightClickDelegate = Function.createDelegate(this, this._onRightClick);
                $addHandler(targetElement, 'contextmenu', this._onRightClickDelegate);              
            }
            
            if (this._showEvent == showEnum.OnFocus)
            {                
                this._onFocusDelegate = Function.createDelegate(this, this._onMouseOver);
                this._onBlurDelegate = Function.createDelegate(this, this._onMouseOut);
                $addHandler(targetElement, 'focus', this._onFocusDelegate);              
                $addHandler(targetElement, 'blur', this._onBlurDelegate);              
            }            
         }
         else
         {         
            if (targetElement)
            {         
                var handlersArray =
                [
                  ["mouseover", this._onMouseOverDelegate],                  
                  ["mousemove", this._onMouseMoveDelegate],
                  ["mouseout", this._onMouseOutDelegate],
                  ["click", this._onClickDelegate],
                  ["contextmenu" ,this._onRightClickDelegate],
                  ["focus", this._onFocusDelegate],
                  ["blur", this._onBlurDelegate]                                                                            
                ];
                
                for (var i = 0; i < handlersArray.length; i++)
                {
                    var item = handlersArray[i];
                    try
                    {
                        if (null != item[1]) $removeHandler(targetElement, item[0], item[1]);                    
                    }catch(e){};
                }
                
                //Force all handlers' delegates to be null to avoid trying to remove a handler twice by mistake
                this._onMouseOverDelegate = null;
                this._onMouseMoveDelegate = null;
                this._onMouseOutDelegate = null;
                this._onClickDelegate = null;
                this._onRightClickDelegate = null;
                this._onFocusDelegate = null;
                this._onBlurDelegate = null;                    
            }       
         }    
    },
    
    
    //To implement sticky behavior and autoclose behavior two handlers must be attached to the popup element 
    //each time it is shown, and detached when it is closed.
    _registerPopupHandlers : function(attachEvent)
     {                
        if (true == attachEvent) //attach
        {
            //Make sticky popup || HACK(when position is Center)
            if (this._sticky || this._position == Telerik.Web.UI.ToolTipPosition.Center)
            {             
                this._popupStickyHandler = Function.createDelegate(this, this._onPopupStickyMouseOut);
                $addHandler(this._tableElement, 'mouseout', this._popupStickyHandler);
                this.set_sticky(true);
            }                                       
        }
        else //detach
        {
            if(this._popupStickyHandler)
            {
                $removeHandler(this._tableElement, 'mouseout', this._popupStickyHandler);
                this._popupStickyHandler = null;
            }            
        } 
     },      


    //Popup Handler #1 - If sticky behavior is enabled, the popup should only close when the mouse is OUT of it - so as to be able to display forms and other rich content.    
    _onPopupStickyMouseOut : function(e)
    {      
        var toKeep = this._isMouseOverElement(e, this._tableElement);        
        if (!toKeep && !this._manualClose)
        {
            this.hide();                
        }
    },
                
    //Popup Handler #2
    /* Not used - causes problem when tooltip displays UpdatePanel 
    with button and clicking on the button to make AJAX request - click event must propagate to the form!
    Instead the tooltip controller code was modified to check whether the click originates from within the tooltip or not
    _onPopupClick : function(e)
    {        
        /// <summary>
        /// Click handler for the tooltip
        /// </summary>
        /// <param name="e" type="Sys.UI.DomEvent">
        /// Event info
        /// </param>
        e.stopPropagation();                
    },            
    */      
                         
    _getPropertiesParameter : function()
    {
        if (!this._propertiesParameter)
        {
           var newPropsParam = {};              
           for (var item in Telerik.Web.UI.RadToolTip.prototype)
           {            
                 var getter = this[item];
                            
                 if (typeof(getter) == 'function' && item.indexOf("get_") == 0)
                 {                           
                    var propName = item.substring(4); 
                                        
                    //If no setter exists, skip property
                    if (null == this["set_" + propName]) continue;              
                    
                    var result = getter.call(this);
                    if (null == result
                        //(typeof(result) != "boolean")                                             
                        //&& (null == result || "" == result)                        
                        ) continue;// -> when result is boolen 'false', the following expression evals to true ->("" == result) ??
                        //NEW: In addition to this "" == 0 also returns true, which is no good
                        //so what should be done is just check for null, and that's it
                   
                    newPropsParam[propName] = result; 
                    
                    //TODO: Implement re-initialization in a better way!
                    //We assume that the Skin property is the last property in a row in the properties list
                    if (propName == "skin") break;                   
                 }
           }            
           
           this._propertiesParameter = newPropsParam;           
        }
                       
       var param = this._cloneObject(this._propertiesParameter);       
       return param;
    },
    
    _getEventsParameter : function()
    {
       if (!this._eventsParameter)
        {
           var newEventsParam = {};
           var events = this.get_events();
                  
           var eventNames = ["beforeShow","show","beforeHide","hide"];
           for (var i=0; i < eventNames.length; i++)
           {
                var name = eventNames[i];
                var evName = events.getHandler(name);
                if (evName && typeof(eval(evName)) == "function")
                {                                    
                    newEventsParam[name] = eval(evName);
                }                    
           }
           this._eventsParameter = newEventsParam;
       }
       return this._eventsParameter;
    },
    
    
    _cloneObject : function(source)
    {
        var target = {};
        for (var item in source)
        {
            target[item] = source[item];
        }
        return target;
    },
                   
     _getPosRelativeToMouse : function(targetBounds)
    {                                     
        var elemX = targetBounds.x;
        var elemY = targetBounds.y;
                
        //Get last recorded mouse position
        var pos = this._getMousePosition();                                                    
        var mouseX = pos.clientX;
        var mouseY = pos.clientY;        
        
        //Take into consideration the offsetScroll!
        var standard = $telerik.standardsMode;
        //$telerik.standardsMode  does not do a good job! Extra check is needed for FF!!
        if (!$telerik.isIE && document.compatMode != "CSS1Compat") standard = false;

        if (standard)
	    {	
	        elemX -= document.documentElement.scrollLeft;
		    elemY -= document.documentElement.scrollTop;		    		    
	    }                                                
	    else //NEW: Add support for quircksmode
	    {
	        elemX -= document.body.scrollLeft;
		    elemY -= document.body.scrollTop;		    		    
	    }                                            
        
        //Calculate the position of the mouse, relative to the targetcontrol        
        var deltaX = mouseX - elemX;
        var deltaY = mouseY - elemY;
        
        return {x : deltaX, y:deltaY};
    },
    
    //These two functions should allow to "get rid" of the mouse event paramenter being passed around in the public API methods
    //Tracking the mouse movements  is internal business to the tooltip. When the API is used, the targetControl should be used calculate position
    //Set by mouse over and mouse move.
    _logMousePosition : function(e)
    {
        if (!e) return;        
        this._mouseX = e.clientX;
        this._mouseY = e.clientY;        
    },
    
    _getMousePosition : function()
    {
        var obj = {};
        obj.clientX = this._mouseX;
        obj.clientY = this._mouseY;
        return obj;
    },
        
    _getCalloutBounds : function()
    {
          var bounds = {
            width : 0,
            height: 0,
            marginLeft : 0,
            marginTop : 0
          };
          
          //Optimization - only if callout should be visible 
          if (this._showCallout && this._calloutElement)        
          {
                bounds.marginLeft = parseInt($telerik.getCurrentStyle(this._calloutElement, 'marginLeft'));
                bounds.marginTop = parseInt($telerik.getCurrentStyle(this._calloutElement, 'marginTop'));          
            
                //Callout might be missing        
                if (isNaN(bounds.marginLeft)) bounds.marginLeft = 0;
                if (isNaN(bounds.marginLeft)) bounds.marginLeft = 0;
                            
                var calloutBounds = $telerik.getBounds(this._calloutElement);
                if (calloutBounds)
                {
                    if (calloutBounds.width) bounds.width  = calloutBounds.width;           
                    if (calloutBounds.height) bounds.height = calloutBounds.height;
                }
           }
           
          return bounds;
    },

    _getBoundsRelativeToBrowser : function(popupBounds, calloutBounds, targetBounds)
    {
        var horSide = this._horizontalPosition;
        var verSide = this._verticalPosition;    
        var x = 0;
        var y = 0;
        
        if (!targetBounds) targetBounds = $telerik.getClientBounds();
        
        //Add scroll offsets
        var scrolls = $telerik.getScrollOffset(document.compatMode && document.compatMode!="BackCompat"? document.documentElement : document.body);    
        
        //When the tooltip is pinned (e.g. its position = fixed, the scrollOffset MUST NOT be calcluated into the positioning.
        if ("fixed" != this._popupElement.style.position)
        {    
            x += scrolls.x;
            y += scrolls.y;
        }

        switch(horSide)
        {
            //Center
            case 2:                            
                 x += - parseInt(popupBounds.width/2 - targetBounds.width/2);
                 x += this._offsetX;
                break;
            //Right
            case 3:              
                x += targetBounds.width;
                x -= popupBounds.width;
                x -= this._offsetX;                        
                break;
                
            //Left            
            case 1:
            default:               
                x += - popupBounds.width;
                x += (- calloutBounds.width - calloutBounds.marginLeft);            
                x += this._offsetX;
                break;
        }            
                      
        //Compute the vertical coordinate
        switch (verSide)
        {
            //Middle
            case 2:               
                y += - parseInt((popupBounds.height - targetBounds.height)/2) ;            
                break;            
            
            //Top    
            case 1:                             
                y += this._offsetY;                               
                break;
            //Bottom
            case 3:
            default:          
                y += targetBounds.height;                            
                y -= this._offsetY;                    
                y -= popupBounds.height;            
                break;                
        }
            
        //Return dimensions     
        return new Sys.UI.Bounds(x, y, popupBounds.width, popupBounds.height);    
    },


    _getBoundsRelativeToElement : function(popupBounds, calloutBounds, targetBounds)
    {
        var horSide = this._horizontalPosition;
        var verSide = this._verticalPosition;    
        var x = 0;
        var y = 0;
        
        //Get targetElement bounds                
        if (!targetBounds) targetBounds = $telerik.getBounds(this._targetControl); 
                                                                                                                                                  
        switch(horSide)
        {
            //Center
            case 2:                            
                 x += - parseInt(popupBounds.width/2 - targetBounds.width/2);
                 x += this._offsetX;
                break;
            //Right
            case 3:              
                x += targetBounds.width;
                x -= calloutBounds.marginLeft;
                x += this._offsetX;
                break;
                
            //Left            
            case 1:
            default:               
                x += - popupBounds.width;
                x += (- calloutBounds.width - calloutBounds.marginLeft);
                x -= this._offsetX;
                break;
        }            
                      
        //Compute the vertical coordinate
        switch (verSide)
        {
            //Middle
            case 2:               
                y += - parseInt(popupBounds.height/2 - targetBounds.height/2) ;
                y += this._offsetY;
                break;            
            
            //Top    
            case 1:                
                y -= popupBounds.height;
                y -= calloutBounds.height + calloutBounds.marginTop;
                y -= this._offsetY;
                break;
            //Bottom
            case 3:
            default:          
                y += targetBounds.height;    
                y -= calloutBounds.marginTop;
                y += this._offsetY;
                break;                
        }
        
        //Return dimensions     
        return new Sys.UI.Bounds(x, y, popupBounds.width, popupBounds.height);    
    },


    _getBoundsRelativeToMouse : function(popupBounds, calloutBounds, targetBounds)
    {        
        //It is possible to call this by a bad mixture of properties, e.g. using code, when no targetElement is set, yet showEvent = Mouse
        var targetBounds = this._targetControl ? $telerik.getBounds(this._targetControl) : $telerik.getClientBounds();
                   
        var pos = this._getPosRelativeToMouse(targetBounds);
             
        //If the event was not triggered from the mouse, it would return NaN for x and y
        if (isNaN(pos.x))
        {
            pos.x = 0;
            pos.y = 0;
        }
        else
        {
            //Set width and height to 0 as this is an illusion for the mouse [target element]    
            targetBounds.width = 0;
            targetBounds.height = 0;
        }
        
        var relativeToElement = this._getBoundsRelativeToElement(popupBounds, calloutBounds, targetBounds);    
        var bounds = new Sys.UI.Bounds(pos.x + relativeToElement.x, pos.y + relativeToElement.y, popupBounds.width, popupBounds.height);
        return bounds;      
    },
        
      getToolTipBounds : function()
     {  
        var popupElement = this._popupElement;                 
        
        //Compute the popupBounds.width and popupBounds.height. Make sure popup is visible at this time        
        var tempHide = (popupElement.style.display == "none") ? true : false;        
        popupElement.style.left = "-3000px";
        popupElement.style.top = "-3000px";
        popupElement.style.display = "";
        
        //Set the overflow
        this._setOverflow();
                
        //NEW: IE! When showing a window for the first time it needs its height fixed        
        if (this._firstShow != true)
        {                    
            this._fixIeHeight(this._tableElement, this._height);              
            this._firstShow = true;
        } 
                
        //NEW: If no target element - set parent element to be relative to browser window,         
        var parent = this._isRelativeToBrowserWindow() ? document.documentElement : this._targetControl;
        this._popupBehavior.set_parentElement(parent);     
                        
        //Get popup bounds        
        var popupBounds = $telerik.getBounds(popupElement);        

        //Get callout offsets        
        var calloutBounds = this._getCalloutBounds();
        
        if (tempHide)
        {
            this._popupElement.style.display = "none";
        }
        
        //Decide which positioning function to use                                                    
        var displayEnum = Telerik.Web.UI.ToolTipRelativeDisplay;
        var showEnum = Telerik.Web.UI.ToolTipShowEvent;
        
        //First to go as being most specific
        var bounds = null;
        if (this._relativeTo == displayEnum.BrowserWindow)
        {         
            bounds = this._getBoundsRelativeToBrowser(popupBounds, calloutBounds);            
        }
        //Save as above - if no target control and showEvent is from code
        else if (!this._targetControl && this._showEvent == showEnum.FromCode)
        {
            bounds = this._getBoundsRelativeToBrowser(popupBounds, calloutBounds);            
        }
        //If target element && showEvent == from code
        else if (this._targetControl && this._showEvent == showEnum.FromCode)
        {        
            bounds = this._getBoundsRelativeToElement(popupBounds, calloutBounds);            
        }
        
        //If popup is to be positioned by the mouse or will be doing mouse trailing                
        else if ((this._mouseTrailing || this._relativeTo == displayEnum.Mouse))
        {                                           
            bounds = this._getBoundsRelativeToMouse(popupBounds, calloutBounds);            
        }        
        else if (this._relativeTo == displayEnum.Element)
        {  
            bounds = this._getBoundsRelativeToElement(popupBounds, calloutBounds);            
        }        
                
        return bounds;                
     },
 
    //Fixes a size bug in IE in DOCTYPE strict mode
    _fixIeHeight : function(oElem, height)
    {    
		if ("CSS1Compat" == document.compatMode) 
		{								
			var difference = (oElem.offsetHeight - parseInt(height));
			if (difference > 0)
			{			
				var newHeight = (parseInt(oElem.style.height) - difference);
				if (newHeight > 0) oElem.style.height = newHeight + "px";
			}
		}
	},

    _refreshTitle : function()
    {
        if (null == this._titleElement) return;
        this._titleElement.innerHTML = this._title;
        this._titleElement.style.display = (this._title) ? "" : "none";                
    },
                                
    _createUI : function()
    {
         //Dynamic rendering of the tooltip
        if (!this._popupElement)
        {        
            var _tooltipId = this.get_id();
            var _wrapperId = 'RadToolTipWrapper_' + _tooltipId;
            
            var _rootDiv = document.createElement('DIV');        
            _rootDiv.id = _wrapperId;                        
                        
            _rootDiv.className = this._getFullSkinName() + (this.get_showCallout() ? " visiblecallout" : "");
                        
            _rootDiv.setAttribute('unselectable', 'on');                
            this._popupElement = _rootDiv;
            
            //Callout        
            var _childDiv = document.createElement('DIV');                
            _childDiv.className = "ToolTipCallout " + this._getCalloutPosition(this._position);                
            _childDiv.innerHTML = "&nbsp;";
            this._calloutElement = _childDiv;

            var _table = document.createElement('TABLE');        
            _table.className = "ToolTipWrapper";        
            _table.style.width = this._width;
            _table.style.height = this._height;
            this._tableElement = _table;
           	
		    //Create the table cells of the tooltip		
            var _classNames = ["ToolTipTopLeft","ToolTipTopCenter","ToolTipTopRight","ToolTipLeftMiddle", "ToolTipContent", 
                               "ToolTipRightMiddle", "ToolTipBottomLeft", "ToolTipBottomCenter", "ToolTipBottomRight"];		
		    var _index = 0;
		    for (var i = 1; i <= 3; i++)
		    {		
		        var _row = _table.insertRow(-1);
		        for (var j = 1; j <= 3; j++)
		        {	  		        
		            var _cell = _row.insertCell(-1);            
		            _cell.innerHTML = "&nbsp;";
		            _cell.className = _classNames[_index];		        
		            _index++;          
    		    }    		
		    }
    						        		
    		var titleCell = _table.rows[0].cells[1];
    		titleCell.innerHTML = "";
    		
    		
    		//Append title element		        		
		    var _titleElement = document.createElement('DIV');
		    _titleElement.className = "ToolTipTitlebar VisibleTitlebar";      		    		    
		    _titleElement.style.display = "none";
		    this._titleElement = _titleElement;
		    this._refreshTitle();		    
		    titleCell.appendChild(_titleElement);
    		    		    		    		
		    //if ManualClose
		    if (this._manualClose)
		    {
		        var _closeElement = document.createElement('A');
		        _closeElement.href = "javascript: void(0);";
		        _closeElement.className = "CloseButton";
    		    		                
		        this._closeLinkHandler = Function.createDelegate(this, function(e)
		        {		        
		           this.hide();
	               if (e)
                   {
                        e.returnValue = false;
                        e.cancelBubble = true;
                        if (e.stopPropagation) e.stopPropagation();
                   }                 
                  return false;
		        });		        
		        $addHandler(_closeElement, 'click', this._closeLinkHandler);
		        this._closeLink = _closeElement;
		        		            		    
		        var _span = document.createElement('SPAN');
		        _span.innerHTML = "Close";//TODO: Localize!
		        _closeElement.title = "Close";
		        _closeElement.appendChild(_span);
		        
		        //Append close element
		        titleCell.appendChild(_closeElement);
		    }
    		
    		//Create content cell
    		var contentCell = _table.rows[1].cells[1];
		    contentCell.vAlign = "top";
		    contentCell.innerHTML = "";//Clear all existing content
		    this._contentCell = contentCell;
    		
    		//Set content
    		//Four scenarios exist here
    		//1 Text property is set
    		//2 Content element is not empty
    		//3 Element has a title attribute
    		//4 Dynamically created tooltip to be used in AJAX load on demand scenario		    
            var serverElement = null;	
            var targetControl = this._targetControl;                        
            
            var text = this.get_text();

//TODO: At present "title" has priority over innercontent - but this has to be FIXED!
//Set content
    		//Three scenarios exist here
    		//1 Text property is set
    		//2 Content element is not empty
    		//3 Dynamically created tooltip to be used in AJAX load on demand scenario
		    //There are two options here - if there is content (other than empty space) in the main DIV, then use it, else use the Text property		  	
            var serverElement = null;		    
		    //If no text is specified, and the tooltip has a title - use it
            var content = this.get_text();
            if (this._targetControl && !content)
            {
                  content = this._targetControl.getAttribute("title");
                  if (content) this._targetControl.removeAttribute("title");     
                  this._text = content;
            }          
		    
    		if (this._text) //Scenario 1
		    {		
		        this.set_content(this._text);		    		           
		    }
    		else //Scenario 2 
    		{
    		    //$get will throw an error if id is empty string
    		    //id can be empty if the tooltip was created as a result of clone method
    		        		    
    		    
    		    var thisId = this.get_id();
    		    if (thisId) serverElement = $get(thisId);
    		    if (serverElement && serverElement.innerHTML)   		    
    		    {
    		      //NEW: Since the DIV element is moved outside the form, it is not disposed if AJAX request is made to an UpdatePanel where the tooltip is
    		      //Removing the ID does not help, so we try transphering the node children to a new node.
    		      //serverElement.removeAttribute("id");
    		      var newElem = this._transferNodeChildren(serverElement);
    		      
    		      this.set_contentElement(newElem);
    		    }
    		}
    		//Scenario 3 - the content element is set at a later stage
    		    		    		      		    		    		    		    						
		    _rootDiv.appendChild(_childDiv);
		    _rootDiv.appendChild(_table);				
            //alert("OUTER HTML "  + this._popupElement.outerHTML);

            //Add to the document        
            this._popupElement.style.display = 'none';
            this._popupElement.style.position = 'absolute';
                       
            this._addToolTipToDocument(serverElement);                                                
        }
        
        //Create the popup if it has not been created
        if (!this._popupBehavior)
        {
            this._popupBehavior = $create(Telerik.Web.PopupBehavior, { 'id': (new Date() - 100)//set a unique id
                +'PopupBehavior', 'parentElement': this._targetControl }, null, null, this._popupElement);
        }        
    },
    
    
    _transferNodeChildren : function(elem)
    {                    
        if (!elem) return null;
                                        
        var newElem = elem.ownerDocument.createElement(elem.tagName);
        
        // Not any more - as we will not replace the original element of the tooltip - this leads to problems when the user replaces the
        // conentElement using the client API and thus removes the clientStateField from the DOM (which we have added as child to the 
        // conentElement).
        
        //It is very important to copy the control attribute to the element, 
        //in case there is such attribute, because this gives information to MS AJAX on dispose
        //if (elem.control) newElem.control = elem.control;
        
//        while (elem.childNodes && elem.childNodes.length > 0)
//        {
//            var curElem = elem.childNodes[0];
//            elem.removeChild(curElem);
//            newElem.appendChild(curElem);
//        }
        
        // We need to keep the clientStateField in its original place, instead of moving it to the content element of the tooltip. 
        // Otherwise, setting new content element, using the client API of the control, would lead to removing the clientStateField
        // from the DOM.
        var childIndexToMove = 0;
        while (elem.childNodes && elem.childNodes.length > childIndexToMove)
        {
            var curElem = elem.childNodes[childIndexToMove];
            
            if(this._clientStateFieldID && curElem.id == this._clientStateFieldID)
            {
                childIndexToMove = 1;
                continue;
            }
            
            elem.removeChild(curElem);
            newElem.appendChild(curElem);
        }
        
        return newElem;
    },
    
    //If the targetControl is a TD or TR we should insert it to the parent table control, or else in IE the tooltip is never visible    
    _addToolTipToDocument : function(elem)
    {    
        // Updated - we should not replace the original <DIV> of the tooltip, as it will hold the clientStateField. Moving the clientStateField
        // to the contentElement of the tooltip leads to problems when the user sets new content element, using the client API of the control,
        // as the clientStateField will be removed from the DOM.
        
        //NEW: Have tooltip replace its original <DIV> after the DIV contents were transfered to a new element. Behaves better in AJAX related scenarios, such as when clicking a button inside the tooltip area that performs and ajax request
        if (null != elem)
        {
            //elem.parentNode.replaceChild(this._popupElement, elem);
            elem.parentNode.insertBefore(this._popupElement, elem);
            return;
        }       
    
        //Append tooltip to end of document               
        var form  = document.getElementById(this._formID);
        if (!form) form = document.forms[0];        
        form.appendChild(this._popupElement);
      
        //This approach would not work in scenarios when tooltips are inserted in update panels that do partial page updates!
        /*
        var badParents = { "TH" : true, "TD" : true, "TR" : true };
        var goodParent = this._targetControl;
        if (badParents[this._targetControl.tagName.toUpperCase()])
        {
            goodParent = this._getParentByTagName(this._targetControl, "TABLE");
        } 
        
        if (goodParent)
        {
            //Sometimes right after an AJAX request the parent node is not yet added in the body
            if (goodParent.parentNode && goodParent.parentNode.insertBefore) 
            {
                goodParent.parentNode.insertBefore(this._popupElement, goodParent);        
            }            
        }
        else 
        {
            alert("Could not insert tooltip element before TargetControl " + this._targetControl);
        }     
        */
    },
     
    _getParentByTagName : function(elem, tagName)
    {
        var parent = elem;
        tagName = tagName.toUpperCase();
        while (parent.tagName.toUpperCase() != tagName)
        {
            parent = parent.parentNode;
            if (!parent) break;
        }        
        return parent;
    },             
    
    _getFullSkinName : function()
    {
        return "radtooltip_" + this._skin;
    },
    
    _getUniqueString : function()
    {
        return "" + (new Date() - 100);
    },    
        
    _getCalloutPosition : function (oPos)
    {
        //If position is left - the callout should be to the right, if position is top, the callout should be to the bottom
        with (Telerik.Web.UI.ToolTipPosition)
        {
            switch(oPos)
            {                
                case TopLeft : return "BottomRight";
                case TopCenter : return "BottomCenter";
                case TopRight : return "BottomLeft";
                case MiddleLeft: return "MiddleRight";
                case Center : return "Center";
                case MiddleRight : return "MiddleLeft";
                case BottomLeft : return "TopRight";
                case BottomCenter : return "TopCenter";
                case BottomRight : return "TopLeft";
            }
        }                
        return "";        
    },
    
    _getHorizontalSide : function(oPos)
    {
      return parseInt((oPos + "").charAt(1));      
    },
    
    _getVerticalSide : function(oPos)
    {
      return parseInt((oPos + "").charAt(0));      
    },
                             
    _setPopupVisible : function(x, y)
    {
        this._popupBehavior.set_x(x);        
        this._popupBehavior.set_y(y);
        this._popupBehavior.show();    

        //Bug in MS AJAX popup implementation sets explicit width, which is not desireable in many scenarios.
        if (!this.get_width())
        {
            this._popupElement.style.width = ""; 
        }

        //Set a large z-index
        this._popupElement.style.zIndex = this._zIndex;                        
    },
    
    //Sets overflow to the tooltip content area on show
    _setOverflow : function()
    {                  
        var flow = this._contentScrolling;
        if (flow == Telerik.Web.UI.ToolTipScrolling.Auto) return;         
                
        var el = this._contentElement;
        //In AJAX scenarios no content element might be present when displaying animation 
        if (!el) return;
        
        var overflow = "";                 
        with (Telerik.Web.UI.ToolTipScrolling)
        {
            switch(flow)
            {                
                case Auto : overflow = "auto"; break;
                case None : overflow = "hidden"; break;
                
                case X : 
                    overflow = "";
                    el.style.overflowX = "scroll";
                    break;
                case Y: 
                    overflow = "";                    
                    el.style.overflowY = "scroll";
                    break;
                case Both : overflow = "scroll";
            }
        }          
                                
        var parent = el.parentNode;        
        el.style.display = "none";
        var height = $telerik.getBounds(parent).height;
        
        el.style.height = height + "px";
        
        //In Mozilla the overflow property overwrites the oveflowX and oveflowY!
        if (!el.style.overflowX && !el.style.overflowY) 
            el.style.overflow = overflow;
                    
        el.style.display = "";
    },
    
     _getLeftOffset : function() {
        /// <summary>
        /// Get the left offset for the tooltip
        /// </summary>
        /// <returns type="Number" integer="true">
        /// Left offset for the tooltip
        /// </returns>         
        var posEnum = Telerik.Web.UI.ToolTipPosition;
        
        if (posEnum.Left == this._position) 
        {
            return (-1 * this._targetControl.offsetWidth) + this._offsetX;
        } 
        else if (posEnum.Right == this._position) 
        {
            return this._targetControl.offsetWidth + this._offsetX;
        }
        else 
        {
            return this._offsetX;
        }
    },

    _getTopOffset : function() {
        /// <summary>
        /// Get the top offset for the tooltip
        /// </summary>
        /// <returns type="Number" integer="true">
        /// Top offset for the tooltip
        /// </returns>        
        var yoffSet;        
        var posEnum = Telerik.Web.UI.ToolTipPosition;
        
        if(posEnum.Top == this._position) 
        {
            yoffSet =  (-1 * this._targetControl.offsetHeight) + this._offsetY;
        }
        else if (posEnum.Bottom == this._position) 
        {
            yoffSet =  this._targetControl.offsetHeight + this._offsetY;
        } 
        else
        {
            yoffSet = this._offsetY;
        }
        
        return yoffSet;
    },
    
                             
    //#####------------------------PUBLIC PROPERTIES ACCESSORS AND MUTATORS------------------------#####//
    isVisible : function()
    {
        /// <summary>
        /// Returns whether the tooltip control is currently visible
        /// </summary>
        /// <value type="Boolean">
        /// Whether the tooltip control is currently visible
        /// </value>
        return this._popupVisible;
    },
    
       
    get_targetControlID : function() {
        /// <summary>
        /// Gets the target control of the tooltip
        /// </summary>
        /// <value type="String">
        /// The ID of the tooltip's target control
        /// </value>
        return this._targetControlID;
    },
    set_targetControlID : function(value)
    {
        /// <summary>
        /// Sets a new target control to the tooltip
        /// </summary>
        /// <param name="value" type="String">
        /// The client id of the target control
        /// </param>
        if (this._targetControlID != value)
        {
            this._targetControlID = value;    
            
            //Set the next target
            var targetControl = (this._targetControlID ? $get(this._targetControlID) : null);
            this.set_targetControl(targetControl);            
        }        
    },
    
       
    get_targetControl: function() 
    {
        /// <summary>
        /// Gets a reference to the tooltip target element
        /// </summary>
        /// <value type="Sys.UI.DomElement">
        /// Returns a reference to the tooltip target element
        /// </value>
        return this._targetControl;
    },
    
    set_targetControl : function(value) 
    {
        /// <summary>
        /// Sets a new target control to the tooltip
        /// </summary>
        /// <param name="value" type="Sys.UI.DomElement">
        /// Reference to the target control
        /// </param>
        if (this._targetControl != value) 
        {              
            //Dispose handlers for old targetControl 
            if (this._targetControl && (this._targetControl != value))
            {                
                this._registerMouseHandlers(this._targetControl, false);
            }
                                                
            //Null is a legitimate value
            this._targetControl = value;            
            
            //Register event handlers on the target object.        
            var targetControl = this._targetControl;
            if (targetControl)
            {            
                //Remove the alt attribute as it screws the effect because it pops up too        
		        if ($telerik.isIE && targetControl)
		        {
		            targetControl.removeAttribute("alt");
		        }
                this._registerMouseHandlers(targetControl, true);     
                
                //Make sure the popup is positioned relative to the new target control!
                if (this._popupBehavior) this._popupBehavior.set_parentElement(targetControl);                
            }
        }                           
    },
    
    
    //Only used by RadToolTip manager to provide information to the AJAX request. Has no influence on tooltip behavior            
    get_serverTargetControlID : function()
    {
        /// <exclude/>
        return this._serverTargetControlID;
    },
       
    set_serverTargetControlID : function(value) 
    {    
        /// <exclude/>    
        this._serverTargetControlID = value;
    },
    
            
    get_serverValue : function()
    {
        /// <exclude/>
        return this._serverValue;
    },
       
    set_serverValue : function(value) 
    {    
        /// <exclude/>    
        this._serverValue = value;
    },
    
    //NEW - for consistency and easiness, set_value and get_value method are added - to be used with AJAX or web services
    get_value : function()
    {
        /// <summary>
        /// Gets the an arbitrary value associated with a tooltip that can be used in scenarios involving AJAX or web services
        /// </summary>
        /// <value type="String">
        /// Returns the value
        /// </value>
        return this.get_serverValue();
    },
    
    set_value : function(value) 
    {    
        /// <summary>
        /// Sets an arbitrary value associated with a tooltip that can be used in scenarios involving AJAX or web services
        /// </summary>
        /// <param name="value" type="String">
        /// Sets the new value
        /// </param>
        this.set_serverValue(value);
    },
           
    
    get_formID : function() 
    {
        /// <exclude />             
        return this._formID;
    },
    
    set_formID : function(value) 
    {
        /// <exclude />             
        if (this._formID != value) { 
            this._formID = value;            
        }
    },

    get_position : function() {
        /// <summary>
        /// Gets the relative position to the tooltip to its target element
        /// </summary>
        /// <value type="Telerik.Web.UI.ToolTipPosition">
        /// Returns the tooltip position relative to the target control
        /// </value>
        return this._position;
    },
    set_position : function(value) 
    {
        /// <summary>
        /// Sets a new relative position to the tooltip to its target element
        /// </summary>
        /// <param name="value" type="Telerik.Web.UI.ToolTipPosition">
        /// The new position value
        /// </param>

        if (this._position != value) {
            this._position = value; 
            
            //Reposition the callout
            if(this._calloutElement) {
                this._calloutElement.className = "ToolTipCallout " + this._getCalloutPosition(this._position); 
            }                                  
        }
        //Cache position settings
        this._horizontalPosition = this._getHorizontalSide(this._position);
        this._verticalPosition = this._getVerticalSide(this._position);
    },

    get_offsetX : function()
    {
        /// <summary>
        /// Gets the horizontal offset relative to its target element
        /// </summary>
        /// <value type="Number" integer="true">
        /// The number of pixels to horizontally offset the Popup from its default position
        /// </value>
        return this._offsetX;
    },
    
    set_offsetX : function(value)
    {
        /// <summary>
        /// Sets a new horizontal offset relative to its target element
        /// </summary>
        /// <param name="value" type="Number" integer="true">
        /// The new OffsetX value
        /// </param>
        if (this._offsetX != value) {
            this._offsetX = value;            
        }
    },

    get_offsetY : function()
    {
        /// <summary>
        /// Gets the vertical offset relative to its target element
        /// </summary>
        /// <value type="Number" integer="true">
        /// The number of pixels to vertically offset the Popup from its default position
        /// </value>
        return this._offsetY;
    },
    
    set_offsetY : function(value) 
    {
        /// <summary>
        /// Sets a new vertical offset relative to its target element
        /// </summary>
        /// <param name="value" type="Number" integer="true">
        /// The new OffsetX value
        /// </param>
        if (this._offsetY != value) {
            this._offsetY = value;            
        }
    },
    
                   
    get_title : function()
    {        
        /// <summary>
        /// Gets the title of the tooltip
        /// </summary>
        /// <value type="String">
        /// The title text of the tooltip
        /// </value>
        return this._title;
    },
    
    set_title : function(value)
    {
        /// <summary>
        /// Sets a new title to the tooltip
        /// </summary>
        /// <param name="value" type="String">
        /// The new title text
        /// </param>
        if (this._title != value) {
            this._title = value;            
        }
        this._refreshTitle();
    },
    
    get_text : function()
    {
        /// <summary>
        /// Gets the text of the tooltip
        /// </summary>
        /// <value type="String">
        /// The text content set to the tooltip
        /// </value>
        return this._text;
    },
    
    set_text : function(value)
    {      
        /// <summary>
        /// Sets new text to the tooltip
        /// </summary>
        /// <param name="value" type="String">
        /// The new text
        /// </param>          
        if (this._text != value) 
        {
            this._text = value;            
        }
                
        if (this.isCreated())
        {
            this.set_content(this._text);
        }
    },
        
    get_width : function()
    {
        /// <summary>
        /// Gets width of the tooltip
        /// </summary>
        /// <value type="Unit">
        /// The original width of the tooltip
        /// </value>
        return this._width;
    },
    
    set_width : function(value) 
    {       
        /// <summary>
        /// Sets new width to the tooltip
        /// </summary>
        /// <param name="value" type="Unit">
        /// The new width
        /// </param>         
        if (this._width != value) {
            this._width = value;            
        }
    },
    
    
    get_height : function()
    {
        /// <summary>
        /// Gets height of the tooltip
        /// </summary>
        /// <value type="Unit">
        /// The original height of the tooltip
        /// </value>
        return this._height;
    },
    
    set_height : function(value)
    {
        /// <summary>
        /// Sets new height to the tooltip
        /// </summary>
        /// <param name="value" type="Unit">
        /// The new height
        /// </param> 
        if (this._height != value) {
            this._height = value;            
        }
    },
               
    get_relativeTo : function()
    {       
        /// <summary>
        /// Gets whether the tooltip is positioned relative to the mouse or relative to the tooltip
        /// </summary>     
        /// <value type="Telerik.Web.UI.ToolTipRelativeDisplay">
        /// The value whether the tooltip is positioned relative to the mouse or relative to the tooltip
        /// </value>
        return this._relativeTo;
    },
    
    set_relativeTo : function(value)
    {
        /// <summary>
        /// Sets whether the tooltip is positioned relative to the mouse or relative to the tooltip
        /// </summary>
        /// <param name="value" type="Telerik.Web.UI.ToolTipRelativeDisplay">
        /// The new value
        /// </param>
        if (this._relativeTo != value) {
            this._relativeTo = value;            
        }
    },
    
    
    get_contentScrolling : function()
    {  
        /// <summary>
        /// Gets a new overflow value for the tooltip content area
        /// </summary>
        /// <value type="Telerik.Web.UI.ToolTipScrolling">
        /// The original overflow setting of the tooltip content area
        /// </value>    
        return this._contentScrolling;
    },
    
    set_contentScrolling : function(value)
    {  
        /// <summary>
        /// Sets a new overflow value for the tooltip content area
        /// </summary>
        /// <param name="value" type="Telerik.Web.UI.ToolTipScrolling">
        /// The new value
        /// </param>    
        if (this._contentScrolling != value) {
            this._contentScrolling = value;
        }
    },
    
    
    get_sticky : function()
    {
        /// <summary>
        /// Gets whether the tooltip is hidden when the mouse leaves the target control, or the tooltip itself
        /// </summary>
        /// <value type="Boolean">
        /// The sticky setting of the tooltip (whether the tooltip is hidden when the mouse leaves the target control, or the tooltip itself)
        /// </value>           
        return this._sticky;
    },
    
    set_sticky : function(value)
    {    
        /// <summary>
        /// Sets whether the tooltip is hidden when the mouse leaves the target control, or the tooltip itself
        /// </summary>
        /// <param name="value" type="Boolean">
        /// The new value
        /// </param>
        if (this._sticky != value) {
            this._sticky = value;            
        }
    },
    
    get_manualClose : function() 
    {    
        /// <summary>
        /// Gets whether the tooltip requires to be hidden manually by the user, or hides automatically
        /// </summary>
        /// <value type="Boolean">
        /// The current value of manual close
        /// </value>      
        return this._manualClose;
    },
    
    set_manualClose : function(value)
    {
        /// <summary>
        /// Sets whether the tooltip requires to be hidden manually by the user, or hides automatically
        /// </summary>
        /// <param name="value" type="Boolean">
        /// The new value
        /// </param>
        if (this._manualClose != value) {
            this._manualClose = value;            
        }
    },
    
    get_showCallout : function()
    {
        /// <exclude/>
        return this._showCallout;
    },
    
    set_showCallout : function(value)
    {
        /// <exclude/>
        if (this._showCallout != value) {
            this._showCallout = value;            
        }
    },
    
            
    get_showDelay : function() { 
        /// <summary>
        /// Gets delay in miliseconds for the tooltip to appear
        /// </summary>
        /// <value type="Number" integer="true">
        /// The current show delay
        /// </value>        
        return this._showDelay;
    },
    
    set_showDelay : function(value) {
        /// <summary>
        /// Sets delay in miliseconds for the tooltip to appear
        /// </summary>
        /// <param name="value" type="Number" integer="true">
        /// The new value
        /// </param>
        if (this._showDelay != value) {
            this._showDelay = value;            
        }
    },
    
           
    get_autoCloseDelay : function()
    {
        /// <summary>
        /// Gets delay in miliseconds for the tooltip to close automatically
        /// </summary>
        /// <value type="Number" integer="true">
        /// The current auto close delay
        /// </value>    
        return this._autoCloseDelay;
    },
    
    set_autoCloseDelay : function(value)
    {
        /// <summary>
        /// Sets delay in miliseconds for the tooltip to close automatically
        /// </summary>
        /// <param name="value" type="Number" integer="true">
        /// The new value
        /// </param>   
        if (this._autoCloseDelay != value) {
            this._autoCloseDelay = value;            
        }
    },
    
    get_hideDelay : function()
    {
        /// <summary>
        /// Gets delay in miliseconds after which the tooltip will hide after the mouse leaves the target element
        /// </summary>
        /// <value type="Number" integer="true">
        /// The current hide delay
        /// </value>    
        return this._hideDelay;
    },
    
    set_hideDelay : function(value)
    {
        /// <summary>
        /// Sets delay in miliseconds for the tooltip to hide after the mouse leaves the target element
        /// </summary>
        /// <param name="value" type="Number" integer="true">
        /// The new value
        /// </param>   
        if (this._hideDelay != value) {
            this._hideDelay = value;            
        }
    },
    
        
    get_mouseTrailing : function()
    {   
        /// <summary>
        /// Gets whether the tooltip should follows the mouse movement or not
        /// </summary>
        /// <value type="Boolean">
        /// The current value whether the tooltip follows the mouse or not
        /// </value>      
        return this._mouseTrailing;
    },
    
    set_mouseTrailing : function(value)
    {
        /// <summary>
        /// Sets whether the tooltip should follows the mouse movement or not
        /// </summary>
        /// <param name="value" type="Boolean" >
        /// The new value
        /// </param>  
        if (this._mouseTrailing != value) {
            this._mouseTrailing = value;            
            
            //Set to follow mouse automatically
            if (true == value) this.set_relativeTo(Telerik.Web.UI.ToolTipRelativeDisplay.Mouse);
        }
    },
    
     get_visibleOnPageLoad: function()
    {
        /// <summary>
        /// Gets a value indicating whether the tooltip will open automatically when its parent [aspx] page is loaded on the client.
        /// </summary>
        /// <value type="Boolean">
        /// The current setting
        /// </value>
        return this._visibleOnPageLoad;
    },
    
    set_visibleOnPageLoad : function(value)
    {
        /// <summary>
        /// Sets a value indicating whether the tooltip will open automatically when its parent [aspx] page is loaded on the client.
        /// </summary>
        /// <param name="value" type="Boolean">
        /// The new setting
        /// </param>  
        if (this._visibleOnPageLoad != value) {
            this._visibleOnPageLoad = value;            
        }
    },
    
    
    get_animation : function()
    {
        /// <summary>
        /// Gets animation value for the tooltip
        /// </summary>
        /// <value type="Telerik.Web.UI.ToolTipAnimation">
        /// The current animation setting
        /// </value>
        return this._animation;
    },
    
    set_animation : function(value)
    {
        /// <summary>
        /// Sets animation value for the tooltip
        /// </summary>
        /// <param name="value" type="Telerik.Web.UI.ToolTipAnimation">
        /// The new value
        /// </param>  
        if (this._animation != value) {
            this._animation = value;            
        }
    },
    
    
    get_showEvent : function() {
        /// <exclude/>
        return this._showEvent;
    },
    
    set_showEvent : function(value) {
        /// <exclude/>
        if (this._showEvent != value) {
            this._showEvent = value;            
        }
    },
      
        
    get_skin : function()
    {
        /// <exclude/>
        return this._skin;
    },
    
    set_skin : function(value)
    {
        /// <exclude/>
        if (value && this._skin != value) 
        {
           this._skin = value;  		   
        }
    },
    
    //New: needed by tooltip manager
    get_popupElement : function()
    {
        /// <exclude/>
        return this._popupElement;
    },
    
    get_modal: function()
    {
        /// <summary>
        /// Gets a value indicating whether a tooltip is modal or not
        /// </summary>
        /// <value type="Boolean">
        /// The current setting
        /// </value>
        return this._modal;
    },
    
    set_modal : function(value)
    {
        /// <summary>
        /// Sets a value indicating whether a tooltip is modal or not
        /// </summary>
        /// <param name="value" type="Boolean">
        /// The new setting
        /// </param>  
        if (this._modal != value) {
            this._modal = value;            
        }
              
        this._makeModal(this._modal);
    },
    
     
    // #region Events                    
    add_beforeShow : function(handler) {
        /// <summary>
        /// Add a handler to the BeforeShow event
        /// </summary>
        /// <param name="handler" type="Function">
        /// Handler
        /// </param>
        this.get_events().addHandler("beforeShow", handler);
    },    
    remove_beforeShow : function(handler) {
        /// <summary>
        /// Remove a handler from the BeforeShow event
        /// </summary>
        /// <param name="handler" type="Function">
        /// Handler
        /// </param>
        this.get_events().removeHandler("beforeShow", handler);
    },
    
    add_show : function(handler) {
        /// <summary>
        /// Add a handler to the Show event
        /// </summary>
        /// <param name="handler" type="Function">
        /// Handler
        /// </param>
        this.get_events().addHandler("show", handler);
    },    
    remove_show : function(handler) {
        /// <summary>
        /// Remove a handler from the Show event
        /// </summary>
        /// <param name="handler" type="Function">
        /// Handler
        /// </param>
        this.get_events().removeHandler("show", handler);
    },
    
    add_beforeHide : function(handler) {
        /// <summary>
        /// Add a handler to the BeforeHide event
        /// </summary>
        /// <param name="handler" type="Function">
        /// Handler
        /// </param>
        this.get_events().addHandler("beforeHide", handler);
    },    
    remove_beforeHide : function(handler) {
        /// <summary>
        /// Remove a handler from the BeforeHide event
        /// </summary>
        /// <param name="handler" type="Function">
        /// Handler
        /// </param>
        this.get_events().removeHandler("beforeHide", handler);
    },
    
    add_hide : function(handler) {
        /// <summary>
        /// Add a handler to the Hide event
        /// </summary>
        /// <param name="handler" type="Function">
        /// Handler
        /// </param>
        this.get_events().addHandler("hide", handler);
    },    
    remove_hide : function(handler) {
        /// <summary>
        /// Remove a handler from the Hide event
        /// </summary>
        /// <param name="handler" type="Function">
        /// Handler
        /// </param>
        this.get_events().removeHandler("hide", handler);
    },
    
            
    saveClientState: function()
    {		
        /// <exclude/>
		var propsToSerialize = [
								"text", "position"								
								];
		var state = {};
         
		for (var i=0; i < propsToSerialize.length; i ++) {
			state[propsToSerialize[i]] = this["get_" + propsToSerialize[i]]();
		}
         
        return Sys.Serialization.JavaScriptSerializer.serialize(state);
    }
}

Telerik.Web.UI.RadToolTip.registerClass('Telerik.Web.UI.RadToolTip', Telerik.Web.UI.RadWebControl);
//    getDescriptor : function() {
//        var td = Telerik.Web.UI.RadToolTip.callBaseMethod(this, 'getDescriptor');
//        // Add custom properties
//        td.addProperty('TargetControlID', String);
//        td.addProperty('Position', String);
//        td.addProperty('OffsetX', Number);
//        td.addProperty('OffsetY', Number);
//        td.addProperty('ExtenderControlID', String);
//        return td;
//    },


Telerik.Web.UI.ToolTipPosition = function() {
    /// <summary>
    /// Position of the tooltip relative to the target control
    /// </summary>
    /// <field name="Center" type="Number" integer="true" />
    /// <field name="Top" type="Number" integer="true" />
    /// <field name="Left" type="Number" integer="true" />
    /// <field name="Bottom" type="Number" integer="true" />
    /// <field name="Right" type="Number" integer="true" />
    throw Error.invalidOperation();
}

//Enum values are set using the following logic: first digit shows vertical and second shows horizontal position
Telerik.Web.UI.ToolTipPosition.prototype = 
{
    TopLeft : 11,
    TopCenter : 12 ,
    TopRight : 13,
    MiddleLeft : 21, 
    Center : 22,
    MiddleRight : 23,
    BottomLeft : 31,
    BottomCenter : 32, 
    BottomRight : 33
};
Telerik.Web.UI.ToolTipPosition.registerEnum("Telerik.Web.UI.ToolTipPosition", false);


Telerik.Web.UI.ToolTipRelativeDisplay = function() {
    /// <summary>
    /// Used to set the RelativeTo property
    /// </summary>
    /// <field name="Element" type="Number" integer="true" />
    /// <field name="Mouse" type="Number" integer="true" />    
    throw Error.invalidOperation();
}
Telerik.Web.UI.ToolTipRelativeDisplay.prototype = 
{    
    Mouse : 0,
    Element : 1,
    BrowserWindow : 2
};
Telerik.Web.UI.ToolTipRelativeDisplay.registerEnum("Telerik.Web.UI.ToolTipRelativeDisplay", false);


Telerik.Web.UI.ToolTipScrolling = function() {
    /// <summary>
    /// Used to set the ContentScrolling property
    /// </summary>
    /// <field name="Auto" type="Number" integer="true" />
    /// <field name="None" type="Number" integer="true" />
    /// <field name="X" type="Number" integer="true" />
    /// <field name="Y" type="Number" integer="true" />
    /// <field name="Both" type="Number" integer="true" />
    throw Error.invalidOperation();
}

Telerik.Web.UI.ToolTipScrolling.prototype = 
{
    Auto : 0,
    None : 1,
    X : 2,
    Y : 3, 
    Both : 4
};
Telerik.Web.UI.ToolTipScrolling.registerEnum("Telerik.Web.UI.ToolTipScrolling", false);


Telerik.Web.UI.ToolTipAnimation = function() {
    /// <summary>
    /// Used to set the Animation property
    /// </summary>    
    /// <field name="None" type="Number" integer="true" />    
    /// <field name="Resize" type="Number" integer="true" />
    /// <field name="Fade" type="Number" integer="true" />
    /// <field name="Slide" type="Number" integer="true" />
    /// <field name="FlyIn" type="Number" integer="true" />
    throw Error.invalidOperation();
}

Telerik.Web.UI.ToolTipAnimation.prototype = 
{
    None : 0,
    Resize: 1,
    Fade : 2,  
    Slide : 4,
    FlyIn : 8
};
Telerik.Web.UI.ToolTipAnimation.registerEnum("Telerik.Web.UI.ToolTipAnimation", false);



Telerik.Web.UI.ToolTipShowEvent = function() {
    /// <summary>
    /// Used to set the ShowEvent property
    /// </summary>    
    /// <field name="OnMouseOver" type="Number" integer="true" />    
    /// <field name="OnClick" type="Number" integer="true" />
    /// <field name="OnRightClick" type="Number" integer="true" />
    /// <field name="OnFocus" type="Number" integer="true" />
    throw Error.invalidOperation();
}

Telerik.Web.UI.ToolTipShowEvent.prototype = 
{
    OnMouseOver : 1,
    OnClick: 2,
    OnRightClick : 4,
    OnFocus : 8,
    FromCode : 16
};
Telerik.Web.UI.ToolTipShowEvent.registerEnum("Telerik.Web.UI.ToolTipShowEvent", false);
/* END Telerik.Web.UI.ToolTip.RadToolTip.js */
/* START Telerik.Web.UI.Common.Animation.Animations.js */
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Permissive License.
// See http://www.microsoft.com/resources/sharedsource/licensingbasics/sharedsourcelicenses.mspx.
// All other rights reserved.

Type.registerNamespace('Telerik.Web.Animation');

// Create an alias for the namespace to save 25 chars each time it's used since
// this is a very long script and will take awhile to download
var $TWA = Telerik.Web.Animation;

$TWA.registerAnimation = function(name, type) {
    /// <summary>
    /// Register an animation with the AJAX Control Toolkit animation framework. This serves a dual purpose:
    /// 1) to add standard utility methods to the animation type (such as a <code>play</code> method that creates
    /// an animation, plays it, and disposes it when the animation is over), and 2) to associate a name with the
    /// type that will be used when creating animations from a JSON description.  This method can also be called
    /// by other animation libraries to seamlessly interoperate with the AJAX Control Toolkit's animation
    /// framework.
    /// </summary>
    /// <param name="name" type="String">
    /// Name of the animation that will be used as the XML tag name in the XML animation description.  It
    /// should be a valid XML tag (i.e. an alpha-numeric sequence with no spaces, special characters, etc.).
    /// </param>
    /// <param name="type" type="Type">
    /// The type of the new animation must inherit from <see cref="Telerik.Web.Animation.Animation" />.
    /// </param>
    /// <returns />

    // Make sure the type inherits from Telerik.Web.Animation.Animation
    if (type && ((type === $TWA.Animation) || (type.inheritsFrom && type.inheritsFrom($TWA.Animation)))) {
        // We'll store the animation name/type mapping in a "static" object off of
        // Telerik.Web.Animation.  If this __animations object hasn't been
        // created yet, demand create it on the first registration.
        if (!$TWA.__animations) {
            $TWA.__animations = { };
        }
        
        // Add the current type to the collection of animations
        $TWA.__animations[name.toLowerCase()] = type;
        
        // Add a play function that will make it very easy to create, play, and
        // dispose of an animation.  This is effectively a "static" function on
        // each animation and will take the same parameters as that animation's
        // constructor.
        type.play = function() {
            /// <summary>
            /// Create an animation, play it immediately, and dispose it when finished.
            /// </summary>
            /// <param parameterArray="true" elementType="Object">
            /// The play function takes the same parameters as the type's constructor
            /// </param>
            /// <returns />
        
            // Create and initialize a new animation of the right type and pass in
            // any arguments given to the play function
            var animation = new type();
            type.apply(animation, arguments);
            animation.initialize();
            
            // Add an event handler to dispose the animation when it's finished
            var handler = Function.createDelegate(animation,
                function() {
                    /// <summary>
                    /// Dispose the animation after playing
                    /// </summary>
                    /// <returns />
                    animation.remove_ended(handler);
                    handler = null;
                    animation.dispose();
                });
            animation.add_ended(handler);
            
            // Once the animation has been created and initialized, play it and
            // dispose it as soon as it's finished
            animation.play();            
        }
    } else {
        // Raise an error if someone registers an animation that doesn't inherit
        // from our base Animation class
        throw Error.argumentType('type', type, $TWA.Animation, "Telerik.Web.Animation.registerAnimation can only register types that inherit from Telerik.Web.Animation.Animation");
    }
}

// In the Xml comments for each of the animations below, there is a special <animation /> tag
// that describes how the animation is referenced from a generic XML animation description


$TWA.Animation = function(target, duration, fps) {
    /// <summary>
    /// <code>Animation</code> is an abstract base class used as a starting point for all the other animations.
    /// It provides the basic mechanics for the animation (playing, pausing, stopping, timing, etc.)
    /// and leaves the actual animation to be done in the abstract methods <code>getAnimatedValue</code>
    /// and <code>setValue</code>.
    /// </summary>
    /// <param name="target" type="Sys.UI.DomElement" mayBeNull="true" optional="true" domElement="true">
    /// Target of the animation
    /// </param>
    /// <param name="duration" type="Number" mayBeNull="true" optional="true">
    /// Length of the animation in seconds.  The default is 1.
    /// </param>
    /// <param name="fps" type="Number" mayBeNull="true" optional="true" integer="true">
    /// Number of steps per second.  The default is 25.
    /// </param>
    /// <field name="DynamicProperties" type="Object">
    /// The DynamicProperties collection is used to associate JavaScript expressions with
    /// properties.  The expressions are evaluated just before the animation is played
    /// everytime (in the base onStart method).  The object itself maps strings with the
    /// names of property setters (like "set_verticalOffset") to JavaScript expressions
    /// (like "$find('MyBehavior').get_element().offsetHeight").  Note specifically that
    /// the dynamic properties are JavaScript expressions and not abitrary statements (i.e.
    /// you can't include things like "return foo;"), although you can include anything
    /// inside an anonymous function definition that you immediately invoke (i.e.,
    /// "(function() { return foo; })()").  A dynamic property can be set in the generic
    /// XML animation description by appending Script onto any legitimate property name
    /// (for example, instead of Height="70" we could use
    /// HeightScript="$find('MyBehavior').get_element().offsetHeight").  Any exceptions
    /// raised when setting dynamic properties (including both JavaScript evaluation errors
    /// and other exceptions raised by property setters) will only be propogated when
    /// debugging.
    /// </field>
    /// <remarks>
    /// Animations need to be as fast as possible - even in debug mode.  Don't add validation code to
    /// methods involved in every step of the animation.
    /// </remarks>
    /// <animation>Animation</animation>
    $TWA.Animation.initializeBase(this);
    
    // Length of the animation in seconds
    this._duration = 1;
    
    // Number of steps per second
    this._fps = 25;
    
    // Target Sys.UI.DomElement of the animation
    this._target = null;
    
    // Tick event handler
    this._tickHandler = null;
    
    // Animation timer
    this._timer = null;
    
    // Percentage of the animation already played
    this._percentComplete = 0;
    
    // Percentage of the animation to play on each step
    this._percentDelta = null;
    
    // Reference to the animation that owns this animation (currently only set in 
    // ParallelAnimation.add).  This concept of ownership allows an entire animation
    // subtree to be driven off a single timer so all the operations are properly
    // synchronized.
    this._owner = null;
    
    // Reference to the animation that contains this as a child (this is set
    // in ParentAnimation.add).  The primary use of the parent animation is in
    // resolving the animation target when one isn't specified.
    this._parentAnimation = null;
    
    // The DynamicProperties collection is used to associate JavaScript expressions with
    // properties.  The expressions are evaluated just before the animation is played
    // everytime (in the base onStart method).  See the additional information in the
    // XML <field> comment above.
    this.DynamicProperties = { };
    
    // Set the target, duration, and fps if they were provided in the constructor
    if (target) {
        this.set_target(target);
    }
    if (duration) {
        this.set_duration(duration);
    }
    if (fps) { 
        this.set_fps(fps);
    }
}
$TWA.Animation.prototype = {
    dispose : function() {
        /// <summary>
        /// Dispose the animation
        /// </summary>
        /// <returns />
        
        if (this._timer) {
            this._timer.dispose();
            this._timer = null;
        }
        
        this._tickHandler = null;
        this._target = null;
        
        $TWA.Animation.callBaseMethod(this, 'dispose');
    },
    
    play : function() {
        /// <summary>
        /// Play the animation from the beginning or where it was left off when paused.
        /// </summary>
        /// <returns />
        /// <remarks>
        /// If this animation is the child of another, you must call <code>play</code> on its parent instead.
        /// </remarks>
        
        // If ownership of this animation has been claimed, then we'll require the parent to
        // handle playing the animation (this is very important because then the entire animation
        // tree runs on the same timer and updates consistently)
        if (!this._owner) {
            var resume = true;
            if (!this._timer) {
                resume = false;
                
                if (!this._tickHandler) {
                    this._tickHandler = Function.createDelegate(this, this._onTimerTick);
                }

                this._timer = new Telerik.Web.Timer();
                this._timer.add_tick(this._tickHandler);
               
                this.onStart();
                
                this._timer.set_interval(1000 / this._fps);
                this._percentDelta = 100 / (this._duration * this._fps);
                this._updatePercentComplete(0, true);
            }

            this._timer.set_enabled(true);
            
            this.raisePropertyChanged('isPlaying');
            if (!resume) {
                this.raisePropertyChanged('isActive');
            }
        }
    },
    
    pause : function() {
        /// <summary>
        /// Pause the animation if it is playing.  Calling <code>play</code> will resume where
        /// the animation left off.
        /// </summary>
        /// <returns />
        /// <remarks>
        /// If this animation is the child of another, you must call <code>pause</code> on its parent instead.
        /// </remarks>
        
        if (!this._owner) {
            if (this._timer) {
                this._timer.set_enabled(false);
                
                this.raisePropertyChanged('isPlaying');
            }
        }
    },
    
    stop : function(finish) {
        /// <summary>
        /// Stop playing the animation.
        /// </summary>
        /// <param name="finish" type="Boolean" mayBeNull="true" optional="true">
        /// Whether or not stopping the animation should leave the target element in a state
        /// consistent with the animation playing completely by performing the last step.
        /// The default value is true.
        /// </param>
        /// <returns />
        /// <remarks>
        /// If this animation is the child of another, you must call <code>stop</code> on
        /// its parent instead.
        /// </remarks>
        
        if (!this._owner) {
            var t = this._timer;
            this._timer = null;
            if (t) {
                t.dispose();
                
                if (this._percentComplete !== 100) {
                    this._percentComplete = 100;
                    this.raisePropertyChanged('percentComplete');
                    if (finish || finish === undefined) {
                        this.onStep(100);
                    }
                }
                this.onEnd();
                
                this.raisePropertyChanged('isPlaying');
                this.raisePropertyChanged('isActive');
            }
        }
    },
    
    onStart : function() {
        /// <summary>
        /// The <code>onStart</code> method is called just before the animation is played each time.
        /// </summary>
        /// <returns />
        
        this.raiseStarted();
        
        // Initialize any dynamic properties
        for (var property in this.DynamicProperties) {
            try {
                // Invoke the property's setter on the evaluated expression
                this[property](eval(this.DynamicProperties[property]));
            } catch(ex) {
                // Propogate any exceptions if we're debugging, otherwise eat them
                if ( Sys.Debug.isDebug) {
                    throw ex;
                }
            }
        }
    },
    
    onStep : function(percentage) {
        /// <summary>
        /// The <code>onStep</code> method is called repeatedly to progress the animation through each frame
        /// </summary>
        /// <param name="percentage" type="Number">Percentage of the animation already complete</param>
        /// <returns />
        
        this.setValue(this.getAnimatedValue(percentage));
    },
    
    onEnd : function() {
        /// <summary>
        /// The <code>onEnd</code> method is called just after the animation is played each time.
        /// </summary>
        /// <returns />
        
        this.raiseEnded();
    },
    
    getAnimatedValue : function(percentage) {
        /// <summary>
        /// Determine the state of the animation after the given percentage of its duration has elapsed
        /// </summary>
        /// <param name="percentage" type="Number">Percentage of the animation already complete</param>
        /// <returns type="Object">
        /// State of the animation after the given percentage of its duration has elapsed that will
        /// be passed to <code>setValue</code>
        /// </returns>
        throw Error.notImplemented();
    },
    
    setValue : function(value) {
        /// <summary>
        /// Set the current state of the animation
        /// </summary>
        /// <param name="value" type="Object">Current state of the animation (as retreived from <code>getAnimatedValue</code>)</param>
        /// <returns />
        throw Error.notImplemented();
    },
    
    interpolate : function(start, end, percentage) {
        /// <summary>
        /// The <code>interpolate</code> function is used to find the appropriate value between starting and
        /// ending values given the current percentage.
        /// </summary>
        /// <param name="start" type="Number">
        /// Start of the range to interpolate
        /// </param>
        /// <param name="end" type="Number">
        /// End of the range to interpolate
        /// </param>
        /// <param name="percentage" type="Number">
        /// Percentage completed in the range to interpolate
        /// </param>
        /// <returns type="Number">
        /// Value the desired percentage between the start and end values
        /// </returns>
        /// <remarks>
        /// In the future, we hope to make several implementations of this available so we can dynamically
        /// change the apparent speed of the animations, although it may make more sense to modify the
        /// <code>_updatePercentComplete</code> function instead.
        /// </remarks>
        return start + (end - start) * (percentage / 100);
    },
    
    _onTimerTick : function() {
        /// <summary>
        /// Handler for the tick event to move the animation along through its duration
        /// </summary>
        /// <returns />
        this._updatePercentComplete(this._percentComplete + this._percentDelta, true);
		this.raise_onTick();
    },
    
    _updatePercentComplete : function(percentComplete, animate) {
        /// <summary>
        /// Update the animation and its target given the current percentage of its duration that
        /// has already elapsed
        /// </summary>
        /// <param name="percentComplete" type="Number">
        /// Percentage of the animation duration that has already elapsed
        /// </param>
        /// <param name="animate" type="Boolean" mayBeNull="true" optional="true">
        /// Whether or not updating the animation should visually modify the animation's target
        /// </param>
        /// <returns />
        
        if (percentComplete > 100) {
            percentComplete = 100;
        }
        
        this._percentComplete = percentComplete;
        this.raisePropertyChanged('percentComplete');
        
        if (animate) {
            this.onStep(percentComplete);
        }
        
        if (percentComplete === 100) {
            this.stop(false);
        }
    },
    
    setOwner : function(owner) {
        /// <summary>
        /// Make this animation the child of another animation
        /// </summary>
        /// <param name="owner" type="Telerik.Web.Animation.Animation">
        /// Parent animation
        /// </param>
        /// <returns />
        this._owner = owner;
    },
    
    raiseStarted : function() {
        /// <summary>
        /// Raise the <code>started</code> event
        /// </summary>
        /// <returns />
        var handlers = this.get_events().getHandler('started');
        if (handlers) {
            handlers(this, Sys.EventArgs.Empty);
        }
    },
    
    add_started : function(handler) {
        /// <summary>
        /// Adds an event handler for the <code>started</code> event.
        /// </summary>
        /// <param name="handler" type="Function">
        /// The handler to add to the event.
        /// </param>
        /// <returns />
        this.get_events().addHandler("started", handler);
    },
    
    remove_started : function(handler) {
        /// <summary>
        /// Removes an event handler for the <code>started</code> event.
        /// </summary>
        /// <param name="handler" type="Function">
        /// The handler to remove from the event.
        /// </param>
        /// <returns />
        this.get_events().removeHandler("started", handler);
    },
    
    raiseEnded : function() {
        /// <summary>
        /// Raise the <code>ended</code> event
        /// </summary>
        /// <returns />
        var handlers = this.get_events().getHandler('ended');
        if (handlers) {
            handlers(this, Sys.EventArgs.Empty);
        }
    },
    
    add_ended : function(handler) {
        /// <summary>
        /// Adds an event handler for the <code>ended</code> event.
        /// </summary>
        /// <param name="handler" type="Function">
        /// The handler to add to the event.
        /// </param>
        /// <returns />
        this.get_events().addHandler("ended", handler);
    },
    
    remove_ended : function(handler) {
        /// <summary>
        /// Removes an event handler for the <code>ended</code> event.
        /// </summary>
        /// <param name="handler" type="Function">
        /// The handler to remove from the event.
        /// </param>
        /// <returns />
        this.get_events().removeHandler("ended", handler);
    },

	raise_onTick : function ()
	{
        var handlers = this.get_events().getHandler('onTick');
        if (handlers)
		{
            handlers(this, Sys.EventArgs.Empty);
        }
	},
	
	add_onTick : function (handler)
	{
		this.get_events().addHandler("onTick", handler);
	},
	
	remove_onTick : function (handler)
	{
		this.get_events().removeHandler("onTick", handler);
	},

    get_target : function() {
        /// <value type="Sys.UI.DomElement" domElement="true" mayBeNull="true">
        /// Target of the animation.  If the target of this animation is null and
        /// the animation has a parent, then it will recursively use the target of
        /// the parent animation instead.
        /// </value>
        /// <remarks>
        /// Do not set this property in a generic Xml animation description. It should be set
        /// using either the extender's TargetControlID or the AnimationTarget property (the latter
        /// maps to Telerik.Web.Animation.set_animationTarget).  The only valid way to
        /// set this property in the generic Xml animation description is to use the dynamic
        /// property TargetScript="$get('myElement')".
        /// <remarks>
        if (!this._target && this._parentAnimation) {
            return this._parentAnimation.get_target();
        }
        return this._target;
    },
    set_target : function(value) {
        if (this._target != value) {
            this._target = value;
            this.raisePropertyChanged('target');
        }
    },
    
    set_animationTarget : function(id) {
        /// <value type="string" mayBeNull="false">
        /// ID of a Sys.UI.DomElement or Sys.UI.Control to use as the target of the animation
        /// </value>
        /// <remarks>
        /// If no Sys.UI.DomElement or Sys.UI.Control can be found for the given ID, an
        /// argument exception will be thrown.
        /// <remarks>
        
        // Try to find a Sys.UI.DomElement
        var target = null;
        var element = $get(id);
        if (element) {
            target = element;
        } else {
            // Try to find the control in the AJAX controls collection
            var ctrl = $find(id);
            if (ctrl) {
                element = ctrl.get_element();
                if (element) {
                    target = element;
                }
            }
        }
        
        // Use the new target if we have one, or raise an error if not
        if (target) { 
            this.set_target(target);
        } else {
            throw Error.argument('id', String.format('Telerik.Web.Animation.Animation.set_animationTarget requires the ID of a Sys.UI.DomElement or Sys.UI.Control.  No element or control could be found corresponding to "{0}"', id));
        }
    },
    
    get_duration : function() {
        /// <value type="Number">
        /// Length of the animation in seconds.  The default is 1.
        /// </value>
        return this._duration;
    },
    set_duration : function(value) {
        value = this._getFloat(value);
        if (this._duration != value) {
            this._duration = value;
            this.raisePropertyChanged('duration');
        }
    },
    
    get_fps : function() {
        /// <value type="Number" integer="true">
        /// Number of steps per second.  The default is 25.
        /// </value>
        return this._fps;
    },
    set_fps : function(value) {
        value = this._getInteger(value);
        if (this.fps != value) {
            this._fps = value;
            this.raisePropertyChanged('fps');
        }
    },
    
    get_isActive : function() {
        /// <value type="Boolean">
        /// <code>true</code> if animation is active, <code>false</code> if not.
        /// </value>
        return (this._timer !== null);
    },
    
    get_isPlaying : function() {
        /// <value type="Boolean">
        /// <code>true</code> if animation is playing, <code>false</code> if not.
        /// </value>
        return (this._timer !== null) && this._timer.get_enabled();
    },
    
    get_percentComplete : function() {
        /// <value type="Number">
        /// Percentage of the animation already played.
        /// </value>
        return this._percentComplete;
    },
    
    _getBoolean : function(value) {
        /// <summary>
        /// Helper to convert strings to booleans for property setters
        /// </summary>
        /// <param name="value" type="Object">
        /// Value to convert if it's a string
        /// </param>
        /// <returns type="Object">
        /// Value that has been converted if it was a string
        /// </returns>
        if (String.isInstanceOfType(value)) {
            return Boolean.parse(value);
        }
        return value;
    },
    
    _getInteger : function(value) {
        /// <summary>
        /// Helper to convert strings to integers for property setters
        /// </summary>
        /// <param name="value" type="Object">Value to convert if it's a string</param>
        /// <returns type="Object">Value that has been converted if it was a string</returns>
        if (String.isInstanceOfType(value)) {
            return parseInt(value);
        }
        return value;
    },
    
    _getFloat : function(value) {
        /// <summary>
        /// Helper to convert strings to floats for property setters
        /// </summary>
        /// <param name="value" type="Object">Value to convert if it's a string</param>
        /// <returns type="Object">Value that has been converted if it was a string</returns>
        if (String.isInstanceOfType(value)) {
            return parseFloat(value);
        }
        return value;
    },
    
    _getEnum : function(value, type) {
        /// <summary>
        /// Helper to convert strings to enum values for property setters
        /// </summary>
        /// <param name="value" type="Object">Value to convert if it's a string</param>
        /// <param name="type" type="Type">Type of the enum to convert to</param>
        /// <returns type="Object">Value that has been converted if it was a string</returns>
        if (String.isInstanceOfType(value) && type && type.parse) {
            return type.parse(value);
        }
        return value;
    }
}
$TWA.Animation.registerClass('Telerik.Web.Animation.Animation', Sys.Component);
$TWA.registerAnimation('animation', $TWA.Animation);


$TWA.ParentAnimation = function(target, duration, fps, animations) {
    /// <summary>
    /// The <code>ParentAnimation</code> serves as a base class for all animations that contain children (such as
    /// <see cref="Telerik.Web.Animation.ParallelAnimation" />, <see cref="Telerik.Web.SequenceAnimation" />,
    /// etc.).  It does not actually play the animations, so any classes that inherit from it must do so.  Any animation
    /// that requires nested child animations must inherit from this class, although it will likely want to inherit off of
    /// <see cref="Telerik.Web.Animation.ParallelAnimation" /> or <see cref="Telerik.Web.SequenceAnimation" />
    /// which will actually play their child animations.
    /// </summary>
    /// <param name="target" type="Sys.UI.DomElement" mayBeNull="true" optional="true" domElement="true">
    /// Target of the animation
    /// </param>
    /// <param name="duration" type="Number" mayBeNull="true" optional="true">
    /// Length of the animation in seconds.  The default is 1.
    /// </param>
    /// <param name="fps" type="Number" mayBeNull="true" optional="true" integer="true">
    /// Number of steps per second.  The default is 25.
    /// </param>
    /// <param name="animations" mayBeNull="true" optional="true" parameterArray="true" elementType="Telerik.Web.Animation.Animation">
    /// Array of child animations to be played
    /// </param>
    /// <animation>Parent</animation>
    $TWA.ParentAnimation.initializeBase(this, [target, duration, fps]);
    
    // Array of child animations (there are no assumptions placed on order because
    // it will matter for some derived animations like SequenceAnimation, but not
    // for others like ParallelAnimation) that is demand created in add
    this._animations = [];
    
    // Add any child animations passed into the constructor
    if (animations && animations.length) {
        for (var i = 0; i < animations.length; i++) {
            this.add(animations[i]);
        }
    }
}
$TWA.ParentAnimation.prototype = {
    initialize : function() {
    	/// <summary>
        /// Initialize the parent along with any child animations that have not yet been initialized themselves
    	/// </summary>
    	/// <returns />
        $TWA.ParentAnimation.callBaseMethod(this, 'initialize');
        
        // Initialize all the uninitialized child animations
        if (this._animations) {
            for (var i = 0; i < this._animations.length; i++) {
                var animation = this._animations[i];
                if (animation && !animation.get_isInitialized) {
                    animation.initialize();
                }
            }
        }
    },
    
    dispose : function() {
    	/// <summary>
        /// Dispose of the child animations
    	/// </summary>
    	/// <returns />

        this.clear();
        this._animations = null;
        $TWA.ParentAnimation.callBaseMethod(this, 'dispose');
    },
    
    get_animations : function() {
    	/// <value elementType="Telerik.Web.Animation.Animation">
        /// Array of child animations to be played (there are no assumptions placed on order because it will matter for some
        /// derived animations like <see cref="Telerik.Web.Animation.SequenceAnimation" />, but not for
        /// others like <see cref="Telerik.Web.Animation.ParallelAnimation" />).  To manipulate the child
        /// animations, use the functions <code>add</code>, <code>clear</code>, <code>remove</code>, and <code>removeAt</code>.
    	/// </value>
        return this._animations;
    },
    
    add : function(animation) {
    	/// <summary>
        /// Add an animation as a child of this animation.
    	/// </summary>
    	/// <param name="animation" type="Telerik.Web.Animation.Animation">Child animation to add</param>
    	/// <returns />

        if (this._animations) {
            if (animation) {
                animation._parentAnimation = this;
            }
            Array.add(this._animations, animation);
            this.raisePropertyChanged('animations');
        }
    },
    
    remove : function(animation) {
        /// <summary>
        /// Remove the animation from the array of child animations.
        /// </summary>
        /// <param name="animation" type="Telerik.Web.Animation.Animation">
        /// Child animation to remove
        /// </param>
        /// <returns />
        /// <remarks>
        /// This will dispose the removed animation.
        /// </remarks>

        if (this._animations) {
            if (animation) {
                animation.dispose();
            }
            Array.remove(this._animations, animation);
            this.raisePropertyChanged('animations');
        }
    },
    
    removeAt : function(index) {
        /// <summary>
        /// Remove the animation at a given index from the array of child animations.
        /// </summary>
        /// <param name="index" type="Number" integer="true">
        /// Index of the child animation to remove
        /// </param>
        /// <returns />
        
        if (this._animations) {
            var animation = this._animations[index];
            if (animation) {
                animation.dispose();
            }
            Array.removeAt(this._animations, index);
            this.raisePropertyChanged('animations');
        }
    },
    
    clear : function() {
    	/// <summary>
        /// Clear the array of child animations.
    	/// </summary>
    	/// <remarks>
    	/// This will dispose the cleared child animations.
    	/// </remarks>
    	/// <returns />

        if (this._animations) {
            for (var i = this._animations.length - 1; i >= 0; i--) {
                this._animations[i].dispose();
                this._animations[i] = null;
            }
            Array.clear(this._animations);
            this._animations = [];
            this.raisePropertyChanged('animations');
        }
    }
}
$TWA.ParentAnimation.registerClass('Telerik.Web.Animation.ParentAnimation', $TWA.Animation);
$TWA.registerAnimation('parent', $TWA.ParentAnimation);


$TWA.ParallelAnimation = function(target, duration, fps, animations) {
    /// <summary>
    /// The <code>ParallelAnimation</code> plays several animations simultaneously.  It inherits from
    /// <see cref="Telerik.Web.Animation.ParentAnimation" />, but makes itself the owner of all
    /// its child animations to allow the use a single timer and syncrhonization mechanisms shared with
    /// all the children (in other words, the <code>duration</code> properties of any child animations
    /// are ignored in favor of the parent's <code>duration</code>).  It is very useful in creating
    /// sophisticated effects through combination of simpler animations.
    /// </summary>
    /// <param name="target" type="Sys.UI.DomElement" mayBeNull="true" optional="true" domElement="true">
    /// Target of the animation
    /// </param>
    /// <param name="duration" type="Number" mayBeNull="true" optional="true">
    /// Length of the animation in seconds.  The default is 1.
    /// </param>
    /// <param name="fps" type="Number" mayBeNull="true" optional="true" integer="true">
    /// Number of steps per second.  The default is 25.
    /// </param>
    /// <param name="animations" mayBeNull="true" optional="true" parameterArray="true" elementType="Telerik.Web.Animation.Animation">
    /// Array of child animations
    /// </param>
    /// <animation>Parallel</animation>
    $TWA.ParallelAnimation.initializeBase(this, [target, duration, fps, animations]);
}
$TWA.ParallelAnimation.prototype = {
    add : function(animation) {
    	/// <summary>
        /// Add an animation as a child of this animation and make ourselves its owner.
    	/// </summary>
    	/// <param name="animation" type="Telerik.Web.Animation.Animation">Child animation to add</param>
    	/// <returns />
        $TWA.ParallelAnimation.callBaseMethod(this, 'add', [animation]);
        animation.setOwner(this);
    },
    
    onStart : function() {
        /// <summary>
        /// Get the child animations ready to play
        /// </summary>
        /// <returns />

        $TWA.ParallelAnimation.callBaseMethod(this, 'onStart');
        var animations = this.get_animations();
        for (var i = 0; i < animations.length; i++) {
            animations[i].onStart();
        }
    },
    
    onStep : function(percentage) {
        /// <summary>
        /// Progress the child animations through each frame
        /// </summary>
        /// <param name="percentage" type="Number">
        /// Percentage of the animation already complete
        /// </param>
        /// <returns />

        var animations = this.get_animations();
        for (var i = 0; i < animations.length; i++) {
            animations[i].onStep(percentage);
        }
    },
    
    onEnd : function() {
        /// <summary>
        /// Finish playing all of the child animations
        /// </summary>
        /// <returns />

        var animations = this.get_animations();
        for (var i = 0; i < animations.length; i++) {
            animations[i].onEnd();
        }
        $TWA.ParallelAnimation.callBaseMethod(this, 'onEnd');
    }
}
$TWA.ParallelAnimation.registerClass('Telerik.Web.Animation.ParallelAnimation', $TWA.ParentAnimation);
$TWA.registerAnimation('parallel', $TWA.ParallelAnimation);

$TWA.FadeEffect = function() {
    /// <summary>
    /// The FadeEffect enumeration determines whether a fade animation is used to fade in or fade out.
    /// </summary>
    /// <field name="FadeIn" type="Number" integer="true" />
    /// <field name="FadeOut" type="Number" integer="true" />
    throw Error.invalidOperation();
}
$TWA.FadeEffect.prototype = {
    FadeIn : 0,
    FadeOut : 1
}
$TWA.FadeEffect.registerEnum("Telerik.Web.Animation.FadeEffect", false);

$TWA.FadeAnimation = function(target, duration, fps, effect, minimumOpacity, maximumOpacity, forceLayoutInIE) {
    /// <summary>
    /// The <code>FadeAnimation</code> is used to fade an element in or out of view, depending on the
    /// provided <see cref="Telerik.Web.Animation.FadeEffect" />, by settings its opacity.
    /// The minimum and maximum opacity values can be specified to precisely control the fade.
    /// You may also consider using <see cref="Telerik.Web.Animation.FadeInAnimation" /> or
    /// <see cref="Telerik.Web.Animation.FadeOutAnimation" /> if you know the only direction you
    /// are fading.
    /// </summary>
    /// <param name="target" type="Sys.UI.DomElement" mayBeNull="true" optional="true" domElement="true">
    /// Target of the animation
    /// </param>
    /// <param name="duration" type="Number" mayBeNull="true" optional="true">
    /// Length of the animation in seconds.  The default is 1.
    /// </param>
    /// <param name="fps" type="Number" mayBeNull="true" optional="true" integer="true">
    /// Number of steps per second.  The default is 25.
    /// </param>
    /// <param name="effect" type="Telerik.Web.Animation.FadeEffect" mayBeNull="true" optional="true">
    /// Determine whether to fade the element in or fade the element out.  The possible values are <code>FadeIn</code>
    /// and <code>FadeOut</code>.  The default value is <code>FadeOut</code>.
    /// </param>
    /// <param name="minimumOpacity" type="Number" mayBeNull="true" optional="true">
    /// Minimum opacity to use when fading in or out. Its value can range from between 0 to 1. The default value is 0.
    /// </param>
    /// <param name="maximumOpacity" type="Number" mayBeNull="true" optional="true">
    /// Maximum opacity to use when fading in or out. Its value can range from between 0 to 1. The default value is 1.
    /// </param>
    /// <param name="forceLayoutInIE" type="Boolean" mayBeNull="true" optional="true">
    /// Whether or not we should force a layout to be created for Internet Explorer by giving it a width and setting its
    /// background color (the latter is required in case the user has ClearType enabled). The default value is <code>true</code>.
    /// This is obviously ignored when working in other browsers.
    /// </param>
    /// <animation>Fade</animation>
    $TWA.FadeAnimation.initializeBase(this, [target, duration, fps]);

    // The effect determines whether or not we fade in or out
    this._effect = (effect !== undefined) ? effect : $TWA.FadeEffect.FadeIn;
    
    // Maximum and minimum opacities default to 100% and 0%
    this._max = (maximumOpacity !== undefined) ? maximumOpacity : 1;
    this._min = (minimumOpacity !== undefined) ? minimumOpacity : 0;
    
    // Starting and ending opacities
    this._start = this._min;
    this._end = this._max;
    
    // Whether the a layout has already been created (to work around IE problems)
    this._layoutCreated = false;

    // Whether or not we should force a layout to be created for IE by giving it a width
    // and setting its background color (the latter is required in case the user has ClearType enabled).
    // http://msdn.microsoft.com/library/default.asp?url=/workshop/author/filter/reference/filters/alpha.asp
    this._forceLayoutInIE = (forceLayoutInIE === undefined || forceLayoutInIE === null) ? true : forceLayoutInIE;
    
    // Current target of the animation that is cached before the animation plays (since looking up
    // the target could mean walking all the way up to the root of the animation's tree, which we don't
    // want to do for every step of the animation)
    this._currentTarget = null;
    
    // Properly set up the min/max values provided by the constructor
    this._resetOpacities();
}
$TWA.FadeAnimation.prototype = {
    _resetOpacities : function() {
    	/// <summary>
        /// Set the starting and ending opacity values based on the effect (i.e. when we're fading
        /// in we go from <code>_min</code> to <code>_max</code>, but we go <code>_max</code> to
        /// <code>_min</code> when fading out)
    	/// </summary>
    	/// <returns />

        if (this._effect == $TWA.FadeEffect.FadeIn) {
            this._start = this._min;
            this._end = this._max;
        } else {
            this._start = this._max;
            this._end = this._min;
        }
    },
    
    _createLayout : function() {
    	/// <summary>
        /// Create a layout when using Internet Explorer (which entails setting a width and also
        /// a background color if it currently has neither)
    	/// </summary>
    	/// <returns />

        var element = this._currentTarget;
        if (element) {
            // Get the original width/height/back color
            var originalWidth = $telerik.getCurrentStyle(element, 'width');
            var originalHeight = $telerik.getCurrentStyle(element, 'height');
            var originalBackColor = $telerik.getCurrentStyle(element, 'backgroundColor');

            // Set the width which will force the creation of a layout
            if ((!originalWidth || originalWidth == '' || originalWidth == 'auto') &&
                (!originalHeight || originalHeight == '' || originalHeight == 'auto')) {
                element.style.width = element.offsetWidth + 'px';
            }
            
            // Set the back color to avoid ClearType problems
            if (!originalBackColor || originalBackColor == '' || originalBackColor == 'transparent' || originalBackColor == 'rgba(0, 0, 0, 0)') {
                element.style.backgroundColor = $telerik.getInheritedBackgroundColor(element);
            }
            
            // Mark that we've created the layout so we only do it once
            this._layoutCreated = true;
        }
    },
    
    onStart : function() {
    	/// <summary>
        /// The <code>onStart</code> method is called just before the animation is played each time.
        /// </summary>
        /// <returns />       
        $TWA.FadeAnimation.callBaseMethod(this, 'onStart');
        
        this._currentTarget = this.get_target();
        this.setValue(this._start);
        
        // Force the creation of a layout in IE if we're supposed to and the current browser is Internet Explorer
        if (this._forceLayoutInIE && !this._layoutCreated && Sys.Browser.agent == Sys.Browser.InternetExplorer) {
            this._createLayout();
        }
    },
    
    getAnimatedValue : function(percentage) {
    	/// <summary>
        /// Determine the current opacity after the given percentage of its duration has elapsed
        /// </summary>
        /// <param name="percentage" type="Number">Percentage of the animation already complete</param>
        /// <returns type="Number">
        /// Current opacity after the given percentage of its duration has elapsed that will
        /// be passed to <code>setValue</code>
        /// </returns>
        return this.interpolate(this._start, this._end, percentage);
    },
    
    setValue : function(value) {
        /// <summary>
        /// Set the current opacity of the element.
        /// </summary>
        /// <param name="value" type="Number">
        /// Current opacity (as retreived from <code>getAnimatedValue</code>)
        /// </param>
        /// <returns />
        /// <remarks>
        /// This method will be replaced by a dynamically generated function that requires no logic
        /// to determine whether it should use filters or the style's opacity.
        /// </remarks>
        if (this._currentTarget) {
            $telerik.setOpacity(this._currentTarget, value);
        }
    },
    
//    set_target : function(value) {
//        /// <value type="Sys.UI.DomElement">
//        /// Override the <code>target</code> property to dynamically create the setValue function.
//        /// </value>
//        /// <remarks>
//        /// Do not set this property in a generic Xml animation description. It will be set automatically
//        /// using either the extender's TargetControlID or the AnimationTarget property.
//        /// <remarks>
//        $TWA.FadeAnimation.callBaseMethod(this, 'set_target', [value]);
//        
//        var element = value;
//        if (element) {
//            var filters = element.filters;
//            if (filters) {
//                var alphaFilter = null;
//                if (filters.length !== 0) {
//                    alphaFilter = filters['DXImageTransform.Microsoft.Alpha'];
//                }
//                if (!alphaFilter) {
//                    element.style.filter = 'progid:DXImageTransform.Microsoft.Alpha(opacity=' + (this._start * 100) + ')';
//                    alphaFilter = filters['DXImageTransform.Microsoft.Alpha'];
//                }
//                if (alphaFilter) {
//                    this.setValue = function(val) { alphaFilter.opacity = val * 100; }
//                } else {
//                    this.setValue = function(val) {
//                        element.style.filter = 'progid:DXImageTransform.Microsoft.Alpha(opacity=' + (val * 100) + ')';
//                    };
//                }
//            }
//            else {
//                this.setValue = function(val) { element.style.opacity = val; };
//            }
//        }
//    },
    
    get_effect : function() {
    	/// <value type="Telerik.Web.Animation.FadeEffect">
        /// Determine whether to fade the element in or fade the element out.  The possible values are
        /// <code>FadeIn</code> and <code>FadeOut</code>.  The default value is <code>FadeOut</code>.
    	/// </value>
        return this._effect;
    },
    set_effect : function(value) {
        value = this._getEnum(value, $TWA.FadeEffect);
        if (this._effect != value) {
            this._effect = value;
            this._resetOpacities();
            this.raisePropertyChanged('effect');
        }
    },
    
    get_minimumOpacity : function() {
        /// <value type="Number">
        /// Minimum opacity to use when fading in or out. Its value can range from between 0 to 1.
        /// The default value is 0.
        /// </value>
	    return this._min;
    },
    set_minimumOpacity : function(value) {
        value = this._getFloat(value);
        if (this._min != value) {
            this._min = value;
            this._resetOpacities();
            this.raisePropertyChanged('minimumOpacity');
        }
    },
    
    get_maximumOpacity : function() {
        /// <value type="Number">
        /// Maximum opacity to use when fading in or out. Its value can range from between 0 to 1.
        /// The default value is 1.
        /// </value>
        return this._max;
    },
    set_maximumOpacity : function(value) {
        value = this._getFloat(value);
        if (this._max != value) {
            this._max = value;
            this._resetOpacities();
            this.raisePropertyChanged('maximumOpacity');
        }
    },
    
    get_forceLayoutInIE : function() {
        /// <value type="Boolean">
        /// Whether or not we should force a layout to be created for Internet Explorer by giving it a width and setting its
        /// background color (the latter is required in case the user has ClearType enabled). The default value is <code>true</code>.
        /// This is obviously ignored when working in other browsers.
        /// </value>
        return this._forceLayoutInIE;
    },
    set_forceLayoutInIE : function(value) {
        value = this._getBoolean(value);
        if (this._forceLayoutInIE != value) {
            this._forceLayoutInIE = value;
            this.raisePropertyChanged('forceLayoutInIE');
        }
    },
    
    set_startValue : function(value) {
        /// <value type="Number">
        /// Set the start value (so that child animations can set the current opacity as the start value when fading in or out)
        /// </value>
        value = this._getFloat(value);
        this._start = value;
    }
}
$TWA.FadeAnimation.registerClass('Telerik.Web.Animation.FadeAnimation', $TWA.Animation);
$TWA.registerAnimation('fade', $TWA.FadeAnimation);


$TWA.FadeInAnimation = function(target, duration, fps, minimumOpacity, maximumOpacity, forceLayoutInIE) {
    /// <summary>
    /// The <code>FadeInAnimation</code> will fade the target in by moving from hidden to visible.
    /// It starts the animation the target's current opacity.
    /// </summary>
    /// <param name="target" type="Sys.UI.DomElement" mayBeNull="true" optional="true" domElement="true">
    /// Target of the animation
    /// </param>
    /// <param name="duration" type="Number" mayBeNull="true" optional="true">
    /// Length of the animation in seconds.  The default is 1.
    /// </param>
    /// <param name="fps" type="Number" mayBeNull="true" optional="true" integer="true">
    /// Number of steps per second.  The default is 25.
    /// </param>
    /// <param name="minimumOpacity" type="Number" mayBeNull="true" optional="true">
    /// Minimum opacity to use when fading in or out. Its value can range from between 0 to 1. The default value is 0.
    /// </param>
    /// <param name="maximumOpacity" type="Number" mayBeNull="true" optional="true">
    /// Maximum opacity to use when fading in or out. Its value can range from between 0 to 1. The default value is 1.
    /// </param>
    /// <param name="forceLayoutInIE" type="Boolean" mayBeNull="true" optional="true">
    /// Whether or not we should force a layout to be created for Internet Explorer by giving it a width and setting its
    /// background color (the latter is required in case the user has ClearType enabled). The default value is <code>true</code>.
    /// This is obviously ignored when working in other browsers.
    /// </param>
    /// <animation>FadeIn</animation>
    $TWA.FadeInAnimation.initializeBase(this, [target, duration, fps, $TWA.FadeEffect.FadeIn, minimumOpacity, maximumOpacity, forceLayoutInIE]);
}
$TWA.FadeInAnimation.prototype = {
    onStart : function() {
    	/// <summary>
        /// The <code>onStart</code> method is called just before the animation is played each time.
        /// </summary>
        /// <returns />
        $TWA.FadeInAnimation.callBaseMethod(this, 'onStart');
        
        if (this._currentTarget) {
            this.set_startValue($telerik.getOpacity(this._currentTarget));
        }
    }
}
$TWA.FadeInAnimation.registerClass('Telerik.Web.Animation.FadeInAnimation', $TWA.FadeAnimation);
$TWA.registerAnimation('fadeIn', $TWA.FadeInAnimation);


$TWA.FadeOutAnimation = function(target, duration, fps, minimumOpacity, maximumOpacity, forceLayoutInIE) {
    /// <summary>
    /// The FadeInAnimation will fade the element out by moving from visible to hidden. It starts the animation
    /// at the element's current opacity.
    /// </summary>
    /// <param name="target" type="Sys.UI.DomElement" mayBeNull="true" optional="true" domElement="true">
    /// Target of the animation
    /// </param>
    /// <param name="duration" type="Number" mayBeNull="true" optional="true">
    /// Length of the animation in seconds.  The default is 1.
    /// </param>
    /// <param name="fps" type="Number" mayBeNull="true" optional="true" integer="true">
    /// Number of steps per second.  The default is 25.
    /// </param>
    /// <param name="minimumOpacity" type="Number" mayBeNull="true" optional="true">
    /// Minimum opacity to use when fading in or out. Its value can range from between 0 to 1. The default value is 0.
    /// </param>
    /// <param name="maximumOpacity" type="Number" mayBeNull="true" optional="true">
    /// Maximum opacity to use when fading in or out. Its value can range from between 0 to 1. The default value is 1.
    /// </param>
    /// <param name="forceLayoutInIE" type="Boolean" mayBeNull="true" optional="true">
    /// Whether or not we should force a layout to be created for Internet Explorer by giving it a width and setting its
    /// background color (the latter is required in case the user has ClearType enabled). The default value is <code>true</code>.
    /// This is obviously ignored when working in other browsers.
    /// </param>
    /// <animation>FadeOut</animation>
    $TWA.FadeOutAnimation.initializeBase(this, [target, duration, fps, $TWA.FadeEffect.FadeOut, minimumOpacity, maximumOpacity, forceLayoutInIE]);
}
$TWA.FadeOutAnimation.prototype = {
    onStart : function() {
    	/// <summary>
        /// The <code>onStart</code> method is called just before the animation is played each time.
        /// </summary>
        /// <returns />
        $TWA.FadeOutAnimation.callBaseMethod(this, 'onStart');

        if (this._currentTarget) {
            this.set_startValue($telerik.getOpacity(this._currentTarget));
        }
    }
}
$TWA.FadeOutAnimation.registerClass('Telerik.Web.Animation.FadeOutAnimation', $TWA.FadeAnimation);
$TWA.registerAnimation('fadeOut', $TWA.FadeOutAnimation);


$TWA.PropertyAnimation = function(target, duration, fps, property, propertyKey) {
    /// <summary>
    /// The <code>PropertyAnimation</code> is a useful base animation that will assign the value from
    /// <code>getAnimatedValue</code> to a specified <code>property</code>. You can provide the name of
    /// a <code>property</code> alongside an optional <code>propertyKey</code> (which indicates the value
    /// <code>property[propertyKey]</code>, like <code>style['backgroundColor']</code>).
    /// </summary>
    /// <param name="target" type="Sys.UI.DomElement" mayBeNull="true" optional="true" domElement="true">
    /// Target of the animation
    /// </param>
    /// <param name="duration" type="Number" mayBeNull="true" optional="true">
    /// Length of the animation in seconds.  The default is 1.
    /// </param>
    /// <param name="fps" type="Number" mayBeNull="true" optional="true" integer="true">
    /// Number of steps per second.  The default is 25.
    /// </param>
    /// <param name="property" type="String" mayBeNull="true" optional="true">
    /// Property of the <code>target</code> element to set when animating
    /// </param>
    /// <param name="propertyKey" type="String" mayBeNull="true" optional="true">
    /// Optional key of the property to be set (which indicates the value property[propertyKey], like style['backgroundColor']). Note that for the style property, the key must be in a JavaScript friendly format (i.e. backgroundColor instead of background-color).
    /// </param>
    /// <animation>Property</animation>
    $TWA.PropertyAnimation.initializeBase(this, [target, duration, fps]);

    // Name of the property to set
    this._property = property;
    
    // Optional Key of the property to set (i.e., if the property were "style" then
    // this might be "backgroundColor")
    this._propertyKey = propertyKey;
    
    // Current target of the animation that is cached before the animation plays (since looking up
    // the target could mean walking all the way up to the root of the animation's tree, which we don't
    // want to do for every step of the animation)
    this._currentTarget = null;
}
$TWA.PropertyAnimation.prototype = {
    onStart : function() {
    	/// <summary>
        /// The <code>onStart</code> method is called just before the animation is played each time.
        /// </summary>
        /// <returns />
        $TWA.PropertyAnimation.callBaseMethod(this, 'onStart');

        this._currentTarget = this.get_target();
    },

    setValue : function(value) {
        /// <summary>
        /// Set the current value of the property
        /// </summary>
        /// <param name="value" type="Object" mayBeNull="true">
        /// Value to assign
        /// </param>
        /// <returns />

        var element = this._currentTarget;
        if (element && this._property && this._property.length > 0) { 
            if (this._propertyKey && this._propertyKey.length > 0 && element[this._property]) {
                element[this._property][this._propertyKey] = value;
            } else {
                element[this._property] = value;
            }
        }
        // Sys.TypeDescriptor.setProperty(this.get_target(), this._property, value, this._propertyKey);
    },
    
    getValue : function() {
        /// <summary>
        /// Get the current value from the property
        /// </summary>
        /// <returns type="Object" mayBeNull="true">
        /// Current value of the property
        /// </returns>

        var element = this.get_target();
        if (element && this._property && this._property.length > 0) { 
            var property = element[this._property];
            if (property) {
                if (this._propertyKey && this._propertyKey.length > 0) {
                    return property[this._propertyKey];
                }
                return property;
            }
        }
        return null;
        // return Sys.TypeDescriptor.getProperty(this.get_target(), this._property, this._propertyKey);
    },
    
    get_property : function() {
        /// <value type="String">
        /// Property of the <code>target</code> element to set when animating
        /// </value>
        return this._property;
    },
    set_property : function(value) {
        if (this._property != value) {
            this._property = value;
            this.raisePropertyChanged('property');
        }
    },
    
    get_propertyKey : function() {
        /// <value type="String" mayBeNull="true" optional="true">
        /// Optional key of the property to be set (which indicates the value property[propertyKey], like style['backgroundColor']). Note that for the style property, the key must be in a JavaScript friendly format (i.e. backgroundColor instead of background-color).
        /// </value>
        return this._propertyKey;
    },
    set_propertyKey : function(value) {
        if (this._propertyKey != value) {
            this._propertyKey = value;
            this.raisePropertyChanged('propertyKey');
        }
    }
}
$TWA.PropertyAnimation.registerClass('Telerik.Web.Animation.PropertyAnimation', $TWA.Animation);
$TWA.registerAnimation('property', $TWA.PropertyAnimation);


$TWA.DiscreteAnimation = function(target, duration, fps, property, propertyKey, values) {
    /// <summary>
    /// The <code>DiscreteAnimation</code> inherits from <see cref="Telerik.Web.Animation.PropertyAnimation" />
    /// and sets the value of the <code>property</code> to the elements in a provided array of <code>values</code>.
    /// </summary>
    /// <param name="target" type="Sys.UI.DomElement" mayBeNull="true" optional="true">
    /// Target of the animation
    /// </param>
    /// <param name="duration" type="Number" mayBeNull="true" optional="true">
    /// Length of the animation in seconds.  The default is 1.
    /// </param>
    /// <param name="fps" type="Number" mayBeNull="true" optional="true">
    /// Number of steps per second.  The default is 25.
    /// </param>
    /// <param name="property" type="String" mayBeNull="true" optional="true">
    /// Property of the <code>target</code> element to set when animating
    /// </param>
    /// <param name="propertyKey" type="String" mayBeNull="true" optional="true">
    /// Optional key of the property to be set (which indicates the value property[propertyKey], like style['backgroundColor']). Note that for the style property, the key must be in a JavaScript friendly format (i.e. backgroundColor instead of background-color).
    /// </param>
    /// <param name="values" mayBeNull="true" optional="true" parameterArray="true" elementType="Object">
    /// Array of possible values of the property that will be iterated over as the animation is played
    /// </param>
    /// <animation>Discrete</animation>
    $TWA.DiscreteAnimation.initializeBase(this, [target, duration, fps, property, propertyKey]);

    // Values to assign to the property
    this._values = (values && values.length) ? values : [];
}
$TWA.DiscreteAnimation.prototype = {
    getAnimatedValue : function(percentage) {
        /// <summary>
        /// Assign the value whose index corresponds to the current percentage
        /// </summary>
        /// <param name="percentage" type="Number">
        /// Percentage of the animation already complete
        /// </param>
        /// <returns type="Object">
        /// State of the animation after the given percentage of its duration has elapsed that will
        /// be passed to <code>setValue</code>
        /// </returns>
        var index = Math.floor(this.interpolate(0, this._values.length - 1, percentage));
        return this._values[index];
    },
    
    get_values : function() {
        /// <value parameterArray="true" elementType="Object">
        /// Array of possible values of the property that will be iterated over as the animation is played
        /// </value>
        return this._values;
    },
    set_values : function(value) {
        if (this._values != value) {
            this._values = value;
            this.raisePropertyChanged('values');
        }
    }
}
$TWA.DiscreteAnimation.registerClass('Telerik.Web.Animation.DiscreteAnimation', $TWA.PropertyAnimation);
$TWA.registerAnimation('discrete', $TWA.DiscreteAnimation);


$TWA.InterpolatedAnimation = function(target, duration, fps, property, propertyKey, startValue, endValue) {
    /// <summary>
    /// The <code>InterpolatedAnimation</code> assigns a range of values between <code>startValue</code>
    /// and <code>endValue</code> to the designated property.
    /// </summary>
    /// <param name="target" type="Sys.UI.DomElement" mayBeNull="true" optional="true" domElement="true">
    /// Target of the animation
    /// </param>
    /// <param name="duration" type="Number" mayBeNull="true" optional="true">
    /// Length of the animation in seconds.  The default is 1.
    /// </param>
    /// <param name="fps" type="Number" mayBeNull="true" optional="true" integer="true">
    /// Number of steps per second.  The default is 25.
    /// </param>
    /// <param name="property" type="String" mayBeNull="true" optional="true">
    /// Property of the <code>target</code> element to set when animating.  The default value is 'style'.
    /// </param>
    /// <param name="propertyKey" type="String" mayBeNull="true" optional="true">
    /// Optional key of the property to be set (which indicates the value property[propertyKey], like style['backgroundColor']). Note that for the style property, the key must be in a JavaScript friendly format (i.e. backgroundColor instead of background-color).
    /// </param>
    /// <param name="startValue" type="Number" mayBeNull="true" optional="true">
    /// Start of the range of values
    /// </param>
    /// <param name="endValue" type="Number" mayBeNull="true" optional="true">
    /// End of the range of values
    /// </param>
    /// <animation>Interpolated</animation>
    $TWA.InterpolatedAnimation.initializeBase(this, [target, duration, fps, ((property !== undefined) ? property : 'style'), propertyKey]);

    // Start and end values
    this._startValue = startValue;
    this._endValue = endValue;
}
$TWA.InterpolatedAnimation.prototype = {
    get_startValue : function() {
        /// <value type="Number">
        /// Start of the range of values
        /// </value>
        return this._startValue;
    },
    set_startValue : function(value) {
        value = this._getFloat(value);
        if (this._startValue != value) {
            this._startValue = value;
            this.raisePropertyChanged('startValue');
        }
    },
    
    get_endValue : function() {
        /// <value type="Number">
        /// End of the range of values
        /// </value>
        return this._endValue;
    },
    set_endValue : function(value) {
        value = this._getFloat(value);
        if (this._endValue != value) {
            this._endValue = value;
            this.raisePropertyChanged('endValue');
        }
    }   
}
$TWA.InterpolatedAnimation.registerClass('Telerik.Web.Animation.InterpolatedAnimation', $TWA.PropertyAnimation);
$TWA.registerAnimation('interpolated', $TWA.InterpolatedAnimation);


$TWA.ColorAnimation = function(target, duration, fps, property, propertyKey, startValue, endValue) {
    /// <summary>
    /// The <code>ColorAnimation</code> transitions the value of the <code>property</code> between
    /// two colors (although it does ignore the alpha channel). The colors must be 7-character hex strings
    /// (like <code>#246ACF</code>).
    /// </summary>
    /// <param name="target" type="Sys.UI.DomElement" mayBeNull="true" optional="true">
    /// Target of the animation
    /// </param>
    /// <param name="duration" type="Number" mayBeNull="true" optional="true">
    /// Length of the animation in seconds.  The default is 1.
    /// </param>
    /// <param name="fps" type="Number" mayBeNull="true" optional="true">
    /// Number of steps per second.  The default is 25.
    /// </param>
    /// <param name="property" type="String" mayBeNull="true" optional="true">
    /// Property of the <code>target</code> element to set when animating.  The default value is 'style'.
    /// </param>
    /// <param name="propertyKey" type="String" mayBeNull="true" optional="true">
    /// Optional key of the property to be set (which indicates the value property[propertyKey], like style['backgroundColor']). Note that for the style property, the key must be in a JavaScript friendly format (i.e. backgroundColor instead of background-color).
    /// </param>
    /// <param name="startValue" type="String" mayBeNull="true" optional="true">
    /// Start of the range of colors
    /// </param>
    /// <param name="endValue" type="String" mayBeNull="true" optional="true">
    /// End of the range of colors
    /// </param>
    /// <animation>Color</animation>
    $TWA.ColorAnimation.initializeBase(this, [target, duration, fps, property, propertyKey, startValue, endValue]);
    
    // Cached start/end RBG triplets
    this._start = null;
    this._end = null;
    
    // Flags indicating whether each dimension of color will be interpolated
    this._interpolateRed = false;
    this._interpolateGreen = false;
    this._interpolateBlue = false;
}
$TWA.ColorAnimation.prototype = {
    onStart : function() {
        /// <summary>
        /// Determine which dimensions of color will be animated
        /// </summary>
        /// <returns />
        $TWA.ColorAnimation.callBaseMethod(this, 'onStart');
       
        this._start = $TWA.ColorAnimation.getRGB(this.get_startValue());
        this._end = $TWA.ColorAnimation.getRGB(this.get_endValue());
        
        this._interpolateRed = (this._start.Red != this._end.Red);
        this._interpolateGreen = (this._start.Green != this._end.Green);
        this._interpolateBlue = (this._start.Blue != this._end.Blue);
    },
    
    getAnimatedValue : function(percentage) {
        /// <summary>
        /// Get the interpolated color values
        /// </summary>
        /// <param name="percentage" type="Number">
        /// Percentage of the animation already complete
        /// </param>
        /// <returns type="String">
        /// Current color formatted as a 7-character hex string (like <code>#246ACF</code>).
        /// </returns>

        var r = this._start.Red;
        var g = this._start.Green;
        var b = this._start.Blue;
        
        if (this._interpolateRed)
            r = Math.round(this.interpolate(r, this._end.Red, percentage));
        
        if (this._interpolateGreen)
            g = Math.round(this.interpolate(g, this._end.Green, percentage));
        
        if (this._interpolateBlue)
            b = Math.round(this.interpolate(b, this._end.Blue, percentage));
        
        return $TWA.ColorAnimation.toColor(r, g, b);
    },
    
    set_startValue : function(value) {
        /// <value type="String">
        /// Starting color of the transition formatted as a 7-character hex string (like <code>#246ACF</code>).
        /// </value>

        if (this._startValue != value) {
            this._startValue = value;
            this.raisePropertyChanged('startValue');
        }
    },
    
    set_endValue : function(value) {
        /// <value type="String">
        /// Ending color of the transition formatted as a 7-character hex string (like <code>#246ACF</code>).
        /// </value>

        if (this._endValue != value) {
            this._endValue = value;
            this.raisePropertyChanged('endValue');
        }
    }   
}
$TWA.ColorAnimation.getRGB = function(color) {
    /// <summary>
    /// Convert the color to an RGB triplet
    /// </summary>
    /// <param name="color" type="String">
    /// Color formatted as a 7-character hex string (like <code>#246ACF</code>)
    /// </param>
    /// <returns type="Object">
    /// Object representing the color with <code>Red</code>, <code>Green</code>, and <code>Blue</code> properties.
    /// </returns>

    if (!color || color.length != 7) {
        throw String.format('Color must be a 7-character hex representation (e.g. #246ACF), not "{0}"', color);
    }
    return { 'Red': parseInt(color.substr(1,2), 16),
             'Green': parseInt(color.substr(3,2), 16),
             'Blue': parseInt(color.substr(5,2), 16) };
}
$TWA.ColorAnimation.toColor = function(red, green, blue) {
    /// <summary>
    /// Convert an RBG triplet into a 7-character hex string (like <code>#246ACF</code>)
    /// </summary>
    /// <param name="red" type="Number" integer="true">
    /// Value of the color's red dimension
    /// </param>
    /// <param name="green" type="Number" integer="true">
    /// Value of the color's green dimension
    /// </param>
    /// <param name="blue" type="Number" integer="true">
    /// Value of the color's blue dimension
    /// </param>
    /// <returns type="String">
    /// Color as a 7-character hex string (like <code>#246ACF</code>)
    /// </returns>

    var r = red.toString(16);
    var g = green.toString(16);
    var b = blue.toString(16);
    if (r.length == 1) r = '0' + r;
    if (g.length == 1) g = '0' + g;
    if (b.length == 1) b = '0' + b;
    return '#' + r + g + b;
}
$TWA.ColorAnimation.registerClass('Telerik.Web.Animation.ColorAnimation', $TWA.InterpolatedAnimation);
$TWA.registerAnimation('color', $TWA.ColorAnimation);


$TWA.LengthAnimation = function(target, duration, fps, property, propertyKey, startValue, endValue, unit) {
    /// <summary>
    /// The <code>LengthAnimation</code> is identical to <see cref="Telerik.Web.Animation.InterpolatedAnimation" />
    /// except it adds a <code>unit</code> to the value before assigning it to the <code>property</code>.
    /// </summary>
    /// <param name="target" type="Sys.UI.DomElement" mayBeNull="true" optional="true">
    /// Target of the animation
    /// </param>
    /// <param name="duration" type="Number" mayBeNull="true" optional="true">
    /// Length of the animation in seconds.  The default is 1.
    /// </param>
    /// <param name="fps" type="Number" mayBeNull="true" optional="true">
    /// Number of steps per second.  The default is 25.
    /// </param>
    /// <param name="property" type="String" mayBeNull="true" optional="true">
    /// Property of the <code>target</code> element to set when animating.  The default value is 'style'.
    /// </param>
    /// <param name="propertyKey" type="String" mayBeNull="true" optional="true">
    /// Optional key of the property to be set (which indicates the value property[propertyKey], like style['backgroundColor']). Note that for the style property, the key must be in a JavaScript friendly format (i.e. backgroundColor instead of background-color).
    /// </param>
    /// <param name="startValue" type="Number" mayBeNull="true" optional="true">
    /// Start of the range of values
    /// </param>
    /// <param name="endValue" type="Number" mayBeNull="true" optional="true">
    /// End of the range of values
    /// </param>
    /// <param name="unit" type="String" mayBeNull="true" optional="true">
    /// Unit of the interpolated values.  The default value is <code>'px'</code>.
    /// </param>
    /// <animation>Length</animation>
    $TWA.LengthAnimation.initializeBase(this, [target, duration, fps, property, propertyKey, startValue, endValue]);
    
    // Unit of length (which defaults to px)
    this._unit = (unit != null) ? unit : 'px';
}
$TWA.LengthAnimation.prototype = {

    getAnimatedValue : function(percentage) {
        /// <summary>
        /// Get the interpolated length value
        /// </summary>
        /// <param name="percentage" type="Number">
        /// Percentage of the animation already complete
        /// </param>
        /// <returns type="String">
        /// Interpolated length
        /// </returns>

        var value = this.interpolate(this.get_startValue(), this.get_endValue(), percentage);
        return Math.round(value) + this._unit;
    },
    
    get_unit : function() {
        /// <value type="String">
        /// Unit of the interpolated values.  The default value is <code>'px'</code>.
        /// </value>
        return this._unit;
    },
    set_unit : function(value) {
        if (this._unit != value) {
            this._unit = value;
            this.raisePropertyChanged('unit');
        }
    }
}
$TWA.LengthAnimation.registerClass('Telerik.Web.Animation.LengthAnimation', $TWA.InterpolatedAnimation);
$TWA.registerAnimation('length', $TWA.LengthAnimation);


$TWA.MoveAnimation = function(target, duration, fps, horizontal, vertical, relative, unit) {
    /// <summary>
    /// The <code>MoveAnimation</code> is used to move the <code>target</code> element. If the
    /// <code>relative</code> flag is set to <code>true</code>, then it treats the <code>horizontal</code>
    /// and <code>vertical</code> properties as offsets to move the element. If the <code>relative</code>
    /// flag is <code>false</code>, then it will treat the <code>horizontal</code> and <code>vertical</code>
    /// properties as coordinates on the page where the <code>target</code> element should be moved. It is
    /// important to note that the <code>target</code> must be positioned (i.e. <code>absolutely</code>) so
    /// that settings its <code>top</code>/<code>left<code> style attributes will change its location.
    /// </summary>
    /// <param name="target" type="Sys.UI.DomElement" mayBeNull="true" optional="true" domElement="true">
    /// Target of the animation
    /// </param>
    /// <param name="duration" type="Number" mayBeNull="true" optional="true">
    /// Length of the animation in seconds.  The default is 1.
    /// </param>
    /// <param name="fps" type="Number" mayBeNull="true" optional="true" integer="true">
    /// Number of steps per second.  The default is 25.
    /// </param>
    /// <param name="horizontal" type="Number" mayBeNull="true" optional="true">
    /// If <code>relative</code>  is <code>true</code>, this is the offset to move horizontally. Otherwise this is the x
    /// coordinate on the page where the <code>target</code> should be moved.
    /// </param>
    /// <param name="vertical" type="Number" mayBeNull="true" optional="true">
    /// If <code>relative</code> is <code>true</code>, this is the offset to move vertically. Otherwise this is the y
    /// coordinate on the page where the <code>target</code> should be moved.
    /// </param>
    /// <param name="relative" type="Boolean" mayBeNull="true" optional="true">
    /// <code>true</code> if we are moving relative to the current position, <code>false</code> if we are moving absolutely
    /// </param>
    /// <param name="unit" type="String" mayBeNull="true" optional="true">
    /// Length unit for the size of the <code>target</code>. The default value is <code>'px'</code>.
    /// </param>
    /// <animation>Move</animation>
    $TWA.MoveAnimation.initializeBase(this, [target, duration, fps, null]);

    // Distance to move horizontally and vertically
    this._horizontal = horizontal ? horizontal : 0;
    this._vertical = vertical ? vertical : 0;
    this._relative = (relative === undefined) ? true : relative;
    
    // Length animations representing the movememnts
    this._horizontalAnimation = new $TWA.LengthAnimation(target, duration, fps, 'style', 'left', null, null, unit);
    this._verticalAnimation = new $TWA.LengthAnimation(target, duration, fps, 'style', 'top', null, null, unit);
    this.add(this._verticalAnimation);
    this.add(this._horizontalAnimation);
}
$TWA.MoveAnimation.prototype = {
    
    onStart : function() {
        /// <summary>
        /// Use the <code>target</code>'s current position as the starting point for the animation
        /// </summary>
        /// <returns />
        $TWA.MoveAnimation.callBaseMethod(this, 'onStart');
        
        // Set the start and end values of the animations by getting
        // the element's current position and applying the offsets
        var element = this.get_target();
        this._horizontalAnimation.set_startValue(element.offsetLeft);
        this._horizontalAnimation.set_endValue(this._relative ? element.offsetLeft + this._horizontal : this._horizontal);
        this._verticalAnimation.set_startValue(element.offsetTop); 
        this._verticalAnimation.set_endValue(this._relative ? element.offsetTop + this._vertical : this._vertical);
    },
    
    get_horizontal : function() {
        /// <value type="Number">
        /// If <code>relative</code>  is <code>true</code>, this is the offset to move horizontally. Otherwise this is the x
        /// coordinate on the page where the <code>target</code> should be moved.
        /// </value>
        return this._horizontal;
    },
    set_horizontal : function(value) {
        value = this._getFloat(value);
        if (this._horizontal != value) {
            this._horizontal = value;
            this.raisePropertyChanged('horizontal');
        }
    },
    
    get_vertical : function() {
        /// <value type="Number">
        /// If <code>relative</code> is <code>true</code>, this is the offset to move vertically. Otherwise this is the y
        /// coordinate on the page where the <code>target</code> should be moved.
        /// </value>
        return this._vertical;
    },
    set_vertical : function(value) {
        value = this._getFloat(value);
        if (this._vertical != value) {
            this._vertical = value;
            this.raisePropertyChanged('vertical');
        }
    },
    
    get_relative : function() {
        /// <value type="Boolean">
        /// <code>true</code> if we are moving relative to the current position, <code>false</code> if we are moving absolutely
        /// </value>
        return this._relative;
    },
    set_relative : function(value) {
        value = this._getBoolean(value);
        if (this._relative != value) {
            this._relative = value;
            this.raisePropertyChanged('relative');
        }
    },
    
    get_unit : function() {
        /// <value type="String" mayBeNull="true">
        /// Length unit for the size of the <code>target</code>. The default value is <code>'px'</code>.
        /// </value>
        this._horizontalAnimation.get_unit();
    },
    set_unit : function(value) {
        var unit = this._horizontalAnimation.get_unit();
        if (unit != value) {
            this._horizontalAnimation.set_unit(value);
            this._verticalAnimation.set_unit(value);
            this.raisePropertyChanged('unit');
        }
    }
}
$TWA.MoveAnimation.registerClass('Telerik.Web.Animation.MoveAnimation', $TWA.ParallelAnimation);
$TWA.registerAnimation('move', $TWA.MoveAnimation);


$TWA.ResizeAnimation = function(target, duration, fps, width, height, unit) {
    /// <summary>
    /// The <code>ResizeAnimation</code> changes the size of the <code>target</code> from its
    /// current value to the specified <code>width</code> and <code>height</code>.
    /// </summary>
    /// <param name="target" type="Sys.UI.DomElement" mayBeNull="true" optional="true" domElement="true">
    /// Target of the animation
    /// </param>
    /// <param name="duration" type="Number" mayBeNull="true" optional="true">
    /// Length of the animation in seconds.  The default is 1.
    /// </param>
    /// <param name="fps" type="Number" mayBeNull="true" optional="true" integer="true">
    /// Number of steps per second.  The default is 25.
    /// </param>
    /// <param name="width" type="Number" mayBeNull="true" optional="true">
    /// New width of the <code>target</code>
    /// </param>
    /// <param name="height" type="Number" mayBeNull="true" optional="true">
    /// New height of the <code>target</code>
    /// </param>
    /// <param name="unit" type="String" mayBeNull="true" optional="true">
    /// Length unit for the size of the <code>target</code>. The default value is <code>'px'</code>.
    /// </param>
    /// <animation>Resize</animation>
    $TWA.ResizeAnimation.initializeBase(this, [target, duration, fps, null]);

    // New size of the element
    this._width = width;
    this._height = height;
    
    // Animations to set the size across both dimensions
    this._horizontalAnimation = new $TWA.LengthAnimation(target, duration, fps, 'style', 'width', null, null, unit);
    this._verticalAnimation = new $TWA.LengthAnimation(target, duration, fps, 'style', 'height', null, null, unit);
    this.add(this._horizontalAnimation);
    this.add(this._verticalAnimation);
}
$TWA.ResizeAnimation.prototype = {
    
    onStart : function() {
        /// <summary>
        /// Use the <code>target</code>'s current size as the starting point for the animation
        /// </summary>
        /// <returns />

        $TWA.ResizeAnimation.callBaseMethod(this, 'onStart');
        
        // Set the start and end values of the animations by getting
        // the element's current width and height
        var element = this.get_target();
        this._horizontalAnimation.set_startValue(element.offsetWidth);
        this._verticalAnimation.set_startValue(element.offsetHeight);
        this._horizontalAnimation.set_endValue((this._width !== null && this._width !== undefined) ?
            this._width : element.offsetWidth);
        this._verticalAnimation.set_endValue((this._height !== null && this._height !== undefined) ?
            this._height : element.offsetHeight);
    },
    
    get_width : function() {
        /// <value type="Number">
        /// New width of the <code>target</code>
        /// </value>

        return this._width;
    },
    set_width : function(value) {
        value = this._getFloat(value);
        if (this._width != value) {
            this._width = value;
            this.raisePropertyChanged('width');
        }
    },
    
    get_height : function() {
        /// <value type="Number">
        /// New height of the <code>target</code>
        /// </value>

        return this._height;
    },
    set_height : function(value) {
        value = this._getFloat(value);
        if (this._height != value) {
            this._height = value;   
            this.raisePropertyChanged('height');
        }
    },
    
    get_unit : function() {
        /// <value type="String">
        /// Length unit for the size of the <code>target</code>. The default value is <code>'px'</code>.
        /// </value>

        this._horizontalAnimation.get_unit();
    },
    set_unit : function(value) {
        var unit = this._horizontalAnimation.get_unit();
        if (unit != value) {
            this._horizontalAnimation.set_unit(value);
            this._verticalAnimation.set_unit(value);
            this.raisePropertyChanged('unit');
        }
    }
}
$TWA.ResizeAnimation.registerClass('Telerik.Web.Animation.ResizeAnimation', $TWA.ParallelAnimation);
$TWA.registerAnimation('resize', $TWA.ResizeAnimation);
/* END Telerik.Web.UI.Common.Animation.Animations.js */
/* START Telerik.Web.UI.Common.Animation.TelerikAnimations.js */
//---------------------------------------- ANIMATIONS --------------------------------------------------//
//Controls to benefit are - tooltip, window, dock, colorpicker
//Animations combine two animations [open/close] using the same set of data.
//Properties that are needed to provide information show and hide animations
//startBounds, endBounds, Telerik.Web.UI.ToolTipPosition position!-> will probably need to be made common for all controls.

//Window can be moved from original location, their opener can be moved, so calculating exact values to use can requier more actions to get the correct values
//Close animations assume the animated element's size and position
Type.registerNamespace('Telerik.Web.UI.Animations');

Telerik.Web.UI.Animations.ShowHideAnimation = function(controller, duration, fps, animatedElement, position, sourceElement) 
{                 
    ///<exclude/>    
    this.controller = controller;
        
    this._duration = (duration !=  null) ? duration : .3;
    this._fps = (fps !=  null) ? fps : 50;
    this._frames = duration * fps;		    
    this._position = null != position ? position : 32;//Telerik.Web.UI.ToolTipPosition.BottomCenter;
        
    this._animatedElement = animatedElement;//The element to be animated    
    this._sourceElement = sourceElement;    //The source element that initiates the animation can be used to obtain start/end bounds
    
    //Start bounds are optional and not set on some animations.If a sourceElement exists, it has higher priority than the startBounds
    this._startBounds = null;
    //End bounds are mandatory for animations that perform resizing, and must be set in onStart handler
    this._endBounds = null;
    
    //Created by classes that inherit the base class
    this._showAnimation = null;
    this._hideAnimation = null;
}


Telerik.Web.UI.Animations.ShowHideAnimation.prototype = 
{   
    //## region protected methods##
    
    //Returns the horizontal position of animated element relative to the sourceElement
    _getHorizontalPosition : function()
    {
      return parseInt((this._position + "").charAt(1));      
    },
    
    //Returns the vertical position of animated element relative to the sourceElement
    _getVerticalPosition : function()
    {
      return parseInt((this._position + "").charAt(0));      
    },
    
    //Use it to set proper values to the animation. 
    //if startBounds are set, use them as initial size/position values. Else - if _sourceElement is set - use its bounds for initial values
    _onBeforeShow : function()
    {    
        /* Override in subclass */
    },
            
    _onBeforeHide : function()
    {    
        /* Override in subclass */
    },
        
    _onAfterShow : function()
    {   
        /* Override in subclass */ 
    },
    
    _onAfterHide : function()
    {   
        /* Override in subclass */ 
    },
                                      
    //## region Public API ##//
    onShowStart : function()
    {
        /* Override when initializing */
    },
            
    onHideStart : function()
    {
        /* Override when initializing */
    },
    
    onShowEnd : function()
    {
       /* Override when initializing */
    },
    onHideEnd : function()
    {
       /* Override when initializing */
    },
    
    play : function(isHideSequence)
    {
        var animation = (true == isHideSequence) ? this._hideAnimation : this._showAnimation;
        
        if (animation)
        {
            //Stop running animation [if any]
            this.stop();
            
            if (!animation.__isTelerikModified)
            {
                var _this = this;
                animation.__isTelerikModified = true;
                
                //Attach to onStart and prevent onStart from being replaced multiple times on each animation play
                var oldStart = animation.onStart;
                animation.onStart = function()
                {                            
                    //Call current onStart to allow for setting configuration values
                    if (isHideSequence) _this.onHideStart();
                    else _this.onShowStart();
              
                    //Use the values set in the onStart event handler to finish the initialization process
                    if (true == isHideSequence)
                    {
                        _this._onBeforeHide();
                    }
                    else
                    {                                  
                        _this._onBeforeShow();          
                    }
                    
                    //Important: Call original onStart to perform initialiation, or else it would not work
                    //! The invocation must be here - as the last action!
                    if (oldStart) oldStart.call(this);
                };
                
                //Attach to onEnd and prevent onEnd from being replaced multiple times on each animation play
                var oldEnd = animation.onEnd;
                animation.onEnd = function()
                {                        
                    if (oldEnd) oldEnd.call(this);
                    if (_this.onEnd) _this.onEnd(isHideSequence);
                    
                    //Cleanup
                    if (true == isHideSequence)
                    {
                        _this._onAfterHide();
                    }
                    else
                    {                                  
                        _this._onAfterShow();          
                    }
                    
                    //Run finalizing code
                    if (isHideSequence) _this.onHideEnd();
                    else _this.onShowEnd();           
                }            
            }
          
            //Play animation            
            animation.play();    
        }
                
        this._runningAnimation = animation;                
    },
    
    set_startBounds : function(bounds)
    {
        this._startBounds = bounds;
    },

    set_endBounds : function(bounds)
    {
        this._endBounds = bounds;
    },
        
    dispose : function()
    {
        this.stop();
        if (this._showAnimation) this._showAnimation.dispose();
        if (this._hideAnimation) this._hideAnimation.dispose();
    },
    
    stop : function()
    {
        if (this._runningAnimation)
        {
            this._runningAnimation.stop();
            this._runningAnimation = null;
        }
    }        
}
Telerik.Web.UI.Animations.ShowHideAnimation.registerClass('Telerik.Web.UI.Animations.ShowHideAnimation', null);


/****************************************************************************************************************
 *                                                  Resize animation 
 ****************************************************************************************************************/
Telerik.Web.UI.Animations.ResizeAnimation = function(controller, duration, fps, animatedElement, position, sourceElement) 
{                 
    Telerik.Web.UI.Animations.ResizeAnimation.initializeBase(this, [controller, duration, fps, animatedElement, position, sourceElement]);    
    
    var duration = this._duration;
    var fps = this._fps;
    var target =  this._animatedElement; 
    
    //Fake values for easier initialiation    
    //var width = 100, height = 100, startY = 0, endY = 100, startX = 0, endX = 100;
    var width, height, startY, endY, startX, endX;
    
	//_showAnimation			
    var resizeAnimation = new Telerik.Web.Animation.ResizeAnimation(target, duration, fps, width, height, 'px');    
    var leftAnimation = new Telerik.Web.Animation.LengthAnimation(target, duration, fps, "style", "left", startX, endX, "px");
    var topAnimation = new Telerik.Web.Animation.LengthAnimation(target, duration, fps, "style", "top", startY, endY, "px");							        
    var fadeAnimation = new Telerik.Web.Animation.FadeInAnimation(target, duration, fps, .3, 1, false);	    						

    this._showAnimation = new Telerik.Web.Animation.ParallelAnimation(target, duration, fps, 		    
                          [resizeAnimation, leftAnimation, topAnimation, fadeAnimation]
                        );                                   
    
    //_hideAnimation
    this._hideAnimation = new Telerik.Web.Animation.FadeInAnimation(this._animatedElement, this._duration, this._fps, 1, 0, false);	               	    
};

Telerik.Web.UI.Animations.ResizeAnimation.prototype = 
{    
    //Break into pieces, some of which will be overridden in ineriting animations
    _configureAnimatedElement : function()
    {
        var target = this._animatedElement;        
        target.style.overflow = "hidden";
        target.style.display = "";
        target.style.visibility = "visible";     
        target.style.width = "1px";
        target.style.height = "1px";        
    },
              
    _configureAnimation : function(animValues)
    {        
        //Configure the animations before you run the parent animation
		var anims = this._showAnimation.get_animations();
		var resizeAnim = anims[0];
		resizeAnim.set_width(animValues.width);
		resizeAnim.set_height(animValues.height);

        var leftAnim = anims[1];     
        leftAnim.set_startValue(animValues.startX);
        leftAnim.set_endValue(animValues.endX);
   
        var topAnim = anims[2];
        topAnim.set_startValue(animValues.startY);
        topAnim.set_endValue(animValues.endY);
    },
        
        
    _getStartBounds : function()
    {
        var startBounds = null;
        if (this._startBounds) startBounds = this._startBounds;
		else if (this._sourceElement) startBounds = $telerik.getBounds(this._sourceElement);
		else startBounds = new Sys.UI.Bounds(1,1,1,1); 	
		return startBounds;
    },
    
    _getEndBounds : function()
    {
        return this._endBounds;
    },
    
    //Can be overridden in subclasses
	_modifyAnimationValues : function(animValues)
    {      			
		//Additional smooth out - if the source element is smaller than tooltip, use the source element as starting size
		var target = this._animatedElement;
		var startBounds = this._getStartBounds();
			                   		
		if(startBounds.width < animValues.width) 
		{
		    animValues.startX = startBounds.x;
		    target.style.width = startBounds.width;
		}
		
		if(startBounds.height < animValues.height) 
		{
		    //Only if position is in center! Other than that -> if position top - start from top, position bottom start from bottom
		    animValues.startY = startBounds.y;				    
            target.style.height = startBounds.height;
		}
	},
		
    _setHorizontalValues : function(animValues)
    {
        var horSide = this._getHorizontalPosition();
        var popupBounds = this._getEndBounds();
        switch(horSide)
        {
            //Center
            case 2:                            
                animValues.startX = popupBounds.x + Math.floor(popupBounds.width/2);  
                animValues.endX = popupBounds.x;
                break;
            //Right
            case 3:              
                animValues.startX = popupBounds.x;
                animValues.endX = popupBounds.x;
                break;                
            //Left            
            case 1:
                animValues.startX = popupBounds.x + popupBounds.width;  
                animValues.endX = popupBounds.x;          
        }
    },
    
    _setVerticalValues : function(animValues)
    {
        var verSide = this._getVerticalPosition();                
        var popupBounds = this._getEndBounds();
         //Compute the vertical coordinate
        switch(verSide)
        {
            //Middle
            case 2:                                               
               animValues.startY = popupBounds.y + Math.floor(popupBounds.height/2);
               animValues.endY = popupBounds.y;
               break;
            //Top    
            case 1:               
               animValues.startY = popupBounds.y + popupBounds.height;
               animValues.endY = popupBounds.y;                
                break;
            //Bottom
            case 3:
               animValues.startY = popupBounds.y;
               animValues.endY = popupBounds.y;             
        }
    },
    
    _setSizeValues : function(animValues)
    {
        var popupBounds = this._endBounds;
        animValues["width"] = popupBounds.width;
		animValues["height"] = popupBounds.height;
    },
    
    //Inherit from parent class
    _onBeforeShow : function()
    {    
		//Create animation object
		var animValues = {};				
		this._setHorizontalValues(animValues);
		this._setVerticalValues(animValues);
		this._setSizeValues(animValues);
	
	    //Configure the element to be animated
		this._configureAnimatedElement();
						                
		//Overridden method - allow for value and target element modification
		this._modifyAnimationValues(animValues);
        //alert("Start x=" + animValues.startX + " , y = " + animValues.startY);
		//Configure the child animation objects using the supplied values
		this._configureAnimation(animValues);
    },
    
    _onAfterShow : function()
    {           
       this._animatedElement.style.overflow = "";        
       //Remove trasnparency filter(s) to make callout visible! Bug in IE         
       this._animatedElement.style.filter = "";               
    }            
}

Telerik.Web.UI.Animations.ResizeAnimation.registerClass('Telerik.Web.UI.Animations.ResizeAnimation', Telerik.Web.UI.Animations.ShowHideAnimation);


/****************************************************************************************************************
 *                                                  Slide animation 
 ****************************************************************************************************************/
 Telerik.Web.UI.Animations.SlideAnimation = function(controller, duration, fps, animatedElement, position, sourceElement) 
{                 
    Telerik.Web.UI.Animations.SlideAnimation.initializeBase(this, [controller, duration, fps, animatedElement, position, sourceElement]);            
};

Telerik.Web.UI.Animations.SlideAnimation.prototype = 
{         
    _modifyAnimationValues : function(animValues)
    {      					
	},
	
	 _configureAnimatedElement : function()
    {
        var target = this._animatedElement;        
        target.style.overflow = "hidden";
        target.style.display = "";
        target.style.visibility = "visible";     
        
        var verSide = this._getVerticalPosition();        
        if (verSide == 2)
        {
           target.style.width = "1px";
        }
        else target.style.height = "1px"; 
    },
		
   _setHorizontalValues : function(animValues)
    {
        var horSide = this._getHorizontalPosition();
        var popupBounds = this._getEndBounds();
        switch(horSide)
        {
            //Center
            case 2:                            
                animValues.startX = popupBounds.x;// + Math.floor(popupBounds.width/2);  
                animValues.endX = popupBounds.x;
                break;
            //Right
            case 3:              
                animValues.startX = popupBounds.x;
                animValues.endX = popupBounds.x;
                break;                
            //Left            
            case 1:
                var startX = popupBounds.x;
                
                if (2 == this._getVerticalPosition())  //Only if vertical pos is middle!
                        startX += popupBounds.width;
                
                animValues.startX = startX;
                                    
                animValues.endX = popupBounds.x;          
        }
    },
    
    _setVerticalValues : function(animValues)
    {
        var verSide = this._getVerticalPosition();                
        var popupBounds = this._getEndBounds();
         //Compute the vertical coordinate
        switch(verSide)
        {
            //Middle
            case 2:                                               
               animValues.startY = popupBounds.y;// + Math.floor(popupBounds.height/2);
               animValues.endY = popupBounds.y;
               break;
            //Top    
            case 1:               
               animValues.startY = popupBounds.y + popupBounds.height;
               animValues.endY = popupBounds.y;                
                break;
            //Bottom
            case 3:
               animValues.startY = popupBounds.y;
               animValues.endY = popupBounds.y;             
        }
    }
}

Telerik.Web.UI.Animations.SlideAnimation.registerClass('Telerik.Web.UI.Animations.SlideAnimation', Telerik.Web.UI.Animations.ResizeAnimation);
 
/****************************************************************************************************************
*                                                  FlyIn animation 
****************************************************************************************************************/
Telerik.Web.UI.Animations.FlyInAnimation = function(controller, duration, fps, animatedElement, position, sourceElement) 
{                 
    Telerik.Web.UI.Animations.FlyInAnimation.initializeBase(this, [controller, duration, fps, animatedElement, position, sourceElement]);    
};

Telerik.Web.UI.Animations.FlyInAnimation.prototype = 
{         
	_modifyAnimationValues : function(animValues)
    {      					
	},
		
    _setHorizontalValues : function(animValues)
    {    
        var horSide = this._getHorizontalPosition();
        var popupBounds = this._getEndBounds();
        
        var browserBounds = $telerik.getClientBounds();
        
        switch(horSide)
        {
            //Center
            case 2:                            
                animValues.startX = popupBounds.x;
                animValues.endX = popupBounds.x;
                break;
            //Right
            case 3:              
                animValues.startX = browserBounds.width;
                animValues.endX =  popupBounds.x;
                break;                
            //Left            
            case 1:
                animValues.startX = browserBounds.x;  
                animValues.endX = popupBounds.x;          
        }
                
    },
    
    _setVerticalValues : function(animValues)
    {
        var verSide = this._getVerticalPosition();                
        var popupBounds = this._getEndBounds();
        var browserBounds = $telerik.getClientBounds();
        
         //Compute the vertical coordinate
        switch(verSide)
        {
            //Middle
            case 2:                                               
               animValues.startY = popupBounds.y;
               animValues.endY = popupBounds.y;
               break;
            //Top    
            case 1:               
               animValues.startY = browserBounds.y - popupBounds.height;
               animValues.endY = popupBounds.y;                
                break;
            //Bottom
            case 3:
               animValues.startY = browserBounds.height;
               animValues.endY = popupBounds.y;             
        }                
    }
}

Telerik.Web.UI.Animations.FlyInAnimation.registerClass('Telerik.Web.UI.Animations.FlyInAnimation', Telerik.Web.UI.Animations.ResizeAnimation);
 
  
/****************************************************************************************************************
*                                                  Fade animation 
****************************************************************************************************************/
Telerik.Web.UI.Animations.FadeAnimation = function(controller, duration, fps, animatedElement) 
{                 
    Telerik.Web.UI.Animations.FadeAnimation.initializeBase(this, [controller, duration, fps, animatedElement]);    
    
    this._showAnimation = new Telerik.Web.Animation.FadeInAnimation(this._animatedElement, this._duration, this._fps, .5, 1, false);	      
    this._hideAnimation = new Telerik.Web.Animation.FadeInAnimation(this._animatedElement, this._duration, this._fps, .9, 0, false);	               
};

Telerik.Web.UI.Animations.FadeAnimation.prototype = 
{      
    _onAfterShow : function()
    {                            
        //Remove trasnparency filter(s) to make callout visible! Bug in IE         
        this._animatedElement.style.filter = "";       
    }       
}

Telerik.Web.UI.Animations.FadeAnimation.registerClass('Telerik.Web.UI.Animations.FadeAnimation', Telerik.Web.UI.Animations.ShowHideAnimation);

/* END Telerik.Web.UI.Common.Animation.TelerikAnimations.js */
if(typeof(Sys)!=='undefined')Sys.Application.notifyScriptLoaded();
(function() {var fn = function() {$get('ctl00_radScriptManager_HiddenField').value += ';;Telerik.Web.UI, Version=2008.1.619.0, Culture=neutral, PublicKeyToken=29ac1a93ec063d92:en-US:cd3bd76e-baab-40e5-81c0-9174afbbbd9d:393f5085:730ff4ad:418b151e:4e368cee:4b40c3e6:9de5f1c7:f336b905';Sys.Application.remove_load(fn);};Sys.Application.add_load(fn);})();
