// (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. // Add common toolkit scripts here. To consume the scripts on a control add // // [RequiredScript(typeof(CommonToolkitScripts))] // public class SomeExtender : ... // // to the controls extender class declaration. Type.registerNamespace('AjaxControlToolkit'); AjaxControlToolkit.BoxSide = function() { /// /// The BoxSide enumeration describes the sides of a DOM element /// /// /// /// /// } AjaxControlToolkit.BoxSide.prototype = { Top : 0, Right : 1, Bottom : 2, Left : 3 } AjaxControlToolkit.BoxSide.registerEnum("AjaxControlToolkit.BoxSide", false); AjaxControlToolkit._CommonToolkitScripts = function() { /// /// The _CommonToolkitScripts class contains functionality utilized across a number /// of controls (but not universally) /// /// /// You should not create new instances of _CommonToolkitScripts. Instead you should use the shared instance CommonToolkitScripts (or AjaxControlToolkit.CommonToolkitScripts). /// // Populate the borderThicknesses lookup table this._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'; this._borderThicknesses['thin'] = div0.offsetHeight - base; div1.style.borderTopWidth = 'medium'; this._borderThicknesses['medium'] = div0.offsetHeight - base; div1.style.borderTopWidth = 'thick'; this._borderThicknesses['thick'] = div0.offsetHeight - base; div0.removeChild(div1); document.body.removeChild(div0); div0 = null; div1 = null; } AjaxControlToolkit._CommonToolkitScripts.prototype = { // The order of these lookup tables is directly linked to the BoxSide enum defined above _borderStyleNames : ['borderTopStyle','borderRightStyle','borderBottomStyle','borderLeftStyle'], _borderWidthNames : ['borderTopWidth', 'borderRightWidth', 'borderBottomWidth', 'borderLeftWidth'], _paddingWidthNames : ['paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft'], getCurrentStyle : function(element, attribute, defaultValue) { /// /// CommonToolkitScripts.getCurrentStyle is used to compute the value of a style attribute on an /// element that is currently being displayed. This is especially useful for scenarios where /// several CSS classes and style attributes are merged, or when you need information about the /// size of an element (such as its padding or margins) that is not exposed in any other fashion. /// /// /// Live DOM element to check style of /// /// /// The style attribute's name is expected to be in a camel-cased form that you would use when /// accessing a JavaScript property instead of the hyphenated form you would use in a CSS /// stylesheet (i.e. it should be "backgroundColor" and not "background-color"). /// /// /// In the event of a problem (i.e. a null element or an attribute that cannot be found) we /// return this object (or null if none if not specified). /// /// /// Current style of the element's attribute /// 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) { /// /// CommonToolkitScripts.getInheritedBackgroundColor provides the ability to get the displayed /// background-color of an element. In most cases calling CommonToolkitScripts.getCurrentStyle /// won't do the job because it will return "transparent" unless the element has been given a /// specific background color. This function will walk up the element's parents until it finds /// a non-transparent color. If we get all the way to the top of the document or have any other /// problem finding a color, we will return the default value '#FFFFFF'. This function is /// especially important when we're using opacity in IE (because ClearType will make text look /// horrendous if you fade it with a transparent background color). /// /// /// Live DOM element to get the background color of /// /// /// Background color of the element /// if (!element) return '#FFFFFF'; var background = this.getCurrentStyle(element, 'backgroundColor'); try { while (!background || background == '' || background == 'transparent' || background == 'rgba(0, 0, 0, 0)') { element = element.parentNode; if (!element) { background = '#FFFFFF'; } else { background = this.getCurrentStyle(element, 'backgroundColor'); } } } catch(ex) { background = '#FFFFFF'; } return background; }, getLocation : function(element) { /// Gets the coordinates of a DOM element. /// /// /// A Point object with two fields, x and y, which contain the pixel coordinates of the 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) 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; // If we're in an iframe, get client coordinates too so we can compute the delta if (element.ownerDocument.parentWindow.frameElement) { // 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; return new Sys.UI.Point(first.left - 2 - dLeft + ownerDocument.scrollLeft, first.top - 2 - dTop + ownerDocument.scrollTop); } return Sys.UI.DomElement.getLocation(element); }, setLocation : function(element, point) { /// /// Sets the current location for an element. /// /// /// DOM element /// /// /// Point object (of the form {x,y}) /// /// /// This method does not attempt to set the positioning mode of an element. /// The position is relative from the elements nearest position:relative or /// position:absolute element. /// Sys.UI.DomElement.setLocation(element, point.x, point.y); }, getContentSize : function(element) { /// /// Gets the "content-box" size of an element. /// /// /// DOM element /// /// /// Size of the element (in the form {width,height}) /// /// /// 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. /// if (!element) { throw Error.argumentNull('element'); } var size = this.getSize(element); var borderBox = this.getBorderBox(element); var paddingBox = this.getPaddingBox(element); return { width : size.width - borderBox.horizontal - paddingBox.horizontal, height : size.height - borderBox.vertical - paddingBox.vertical } }, getSize : function(element) { /// /// Gets the "border-box" size of an element. /// /// /// DOM element /// /// /// Size of the element (in the form {width,height}) /// /// /// 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. /// if (!element) { throw Error.argumentNull('element'); } return { width: element.offsetWidth, height: element.offsetHeight }; }, setContentSize : function(element, size) { /// /// Sets the "content-box" size of an element. /// /// /// DOM element /// /// /// Size of the element (in the form {width,height}) /// /// /// 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. /// 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(this.getCurrentStyle(element, 'MozBoxSizing') == 'border-box' || this.getCurrentStyle(element, 'BoxSizing') == 'border-box') { var borderBox = this.getBorderBox(element); var paddingBox = this.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) { /// /// Sets the "border-box" size of an element. /// /// /// 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. /// /// DOM element /// Size of the element (in the form {width,height}) /// if (!element) { throw Error.argumentNull('element'); } if (!size) { throw Error.argumentNull('size'); } var borderBox = this.getBorderBox(element); var paddingBox = this.getPaddingBox(element); var contentSize = { width: size.width - borderBox.horizontal - paddingBox.horizontal, height: size.height - borderBox.vertical - paddingBox.vertical }; this.setContentSize(element, contentSize); }, getBounds : function(element) { /// Gets the coordinates, width and height of an element. /// /// /// A Bounds object with four fields, x, y, width and height, which contain the pixel coordinates, /// width and height of the element. /// /// /// Use the CommonToolkitScripts version of getLocation to handle the workaround for IE6. We can /// remove the below implementation and just call Sys.UI.DomElement.getBounds when the other bug /// is fixed. /// var offset = CommonToolkitScripts.getLocation(element); return new Sys.UI.Bounds(offset.x, offset.y, element.offsetWidth || 0, element.offsetHeight || 0); }, setBounds : function(element, bounds) { /// /// Sets the "border-box" bounds of an element /// /// /// DOM element /// /// /// Bounds of the element (of the form {x,y,width,height}) /// /// /// 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. /// if (!element) { throw Error.argumentNull('element'); } if (!bounds) { throw Error.argumentNull('bounds'); } this.setSize(element, bounds); CommonToolkitScripts.setLocation(element, bounds); }, getClientBounds : function() { /// /// Gets the width and height of the browser client window (excluding scrollbars) /// /// /// Browser's client width and height /// var clientWidth; var clientHeight; switch(Sys.Browser.agent) { case Sys.Browser.InternetExplorer: clientWidth = document.documentElement.clientWidth; clientHeight = document.documentElement.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); }, getBorderBox : function(element) { /// /// Gets the entire border box sizes. /// /// /// DOM element /// /// /// Element's border box sizes (of the form {top,left,bottom,right,horizontal,vertical}) /// if (!element) { throw Error.argumentNull('element'); } var box = { top: this.getBorderWidth(element, AjaxControlToolkit.BoxSide.Top), right: this.getBorderWidth(element, AjaxControlToolkit.BoxSide.Right), bottom: this.getBorderWidth(element, AjaxControlToolkit.BoxSide.Bottom), left: this.getBorderWidth(element, AjaxControlToolkit.BoxSide.Left) } box.horizontal = box.left + box.right; box.vertical = box.top + box.bottom; return box; }, getPaddingBox : function(element) { /// /// Gets the entire padding box sizes. /// /// /// DOM element /// /// /// Element's padding box sizes (of the form {top,left,bottom,right,horizontal,vertical}) /// if (!element) { throw Error.argumentNull('element'); } var box = { top: this.getPadding(element, AjaxControlToolkit.BoxSide.Top), right: this.getPadding(element, AjaxControlToolkit.BoxSide.Right), bottom: this.getPadding(element, AjaxControlToolkit.BoxSide.Bottom), left: this.getPadding(element, AjaxControlToolkit.BoxSide.Left) } box.horizontal = box.left + box.right; box.vertical = box.top + box.bottom; return box; }, isBorderVisible : function(element, boxSide) { /// /// Gets whether the current border style for an element on a specific boxSide is not 'none'. /// /// /// DOM element /// /// /// Side of the element /// /// /// Whether the current border style for an element on a specific boxSide is not 'none'. /// if (!element) { throw Error.argumentNull('element'); } if(boxSide < AjaxControlToolkit.BoxSide.Top || boxSide > AjaxControlToolkit.BoxSide.Left) { throw Error.argumentOutOfRange("Argument 'boxSide' out of the range of expected values"); } var styleName = this._borderStyleNames[boxSide]; var styleValue = this.getCurrentStyle(element, styleName); return styleValue != "none"; }, getBorderWidth : function(element, boxSide) { /// /// Gets the border thickness of an element on a specific boxSide. /// /// /// DOM element /// /// /// Side of the element /// /// /// Border thickness on the element's specified side /// if (!element) { throw Error.argumentNull('element'); } if(boxSide < AjaxControlToolkit.BoxSide.Top || boxSide > AjaxControlToolkit.BoxSide.Left) { throw Error.argumentOutOfRange("Argument 'boxSide' out of the range of expected values"); } if(!this.isBorderVisible(element, boxSide)) { return 0; } var styleName = this._borderWidthNames[boxSide]; var styleValue = this.getCurrentStyle(element, styleName); return this.parseBorderWidth(styleValue); }, getPadding : function(element, boxSide) { /// /// Gets the padding thickness of an element on a specific boxSide. /// /// /// DOM element /// /// /// Side of the element /// /// /// Padding on the element's specified side /// if (!element) { throw Error.argumentNull('element'); } if(boxSide < AjaxControlToolkit.BoxSide.Top || boxSide > AjaxControlToolkit.BoxSide.Left) { throw Error.argumentOutOfRange("Argument 'boxSide' out of the range of expected values"); } var styleName = this._paddingWidthNames[boxSide]; var styleValue = this.getCurrentStyle(element, styleName); return this.parsePadding(styleValue); }, parseBorderWidth : function(borderWidth) { /// /// Parses a border-width string into a pixel size /// /// /// Type of border ('thin','medium','thick','inherit',px unit,null,'') /// /// /// Number of pixels in the border-width /// if(borderWidth) { switch(borderWidth) { case 'thin': case 'medium': case 'thick': return this._borderThicknesses[borderWidth]; case 'inherit': return 0; } var unit = this.parseUnit(borderWidth); Sys.Debug.assert(unit.type == 'px', 'A unit type of ' + unit.type + ' is invalid for parseBorderWidth'); return unit.size; } return 0; }, parsePadding : function(padding) { /// /// Parses a padding string into a pixel size /// /// /// Padding to parse ('inherit',px unit,null,'') /// /// /// Number of pixels in the padding /// if(padding) { if(padding == 'inherit') { return 0; } var unit = this.parseUnit(padding); Sys.Debug.assert(unit.type == 'px', 'A unit type of ' + unit.type + ' is invalid for parsePadding'); return unit.size; } return 0; }, parseUnit : function(value) { /// /// Parses a unit string into a unit object /// /// /// Value to parse (of the form px unit,% unit,em unit,...) /// /// /// Parsed unit (of the form {size,type}) /// 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 }; }, getElementOpacity : function(element) { /// /// Get the element's opacity /// /// /// Element /// /// /// Opacity of the element /// if (!element) { throw Error.argumentNull('element'); } var hasOpacity = false; var opacity; 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 = this.getCurrentStyle(element, 'opacity', 1); // var computedStyle = document.defaultView.getComputedStyle; // opacity = computedStyle(element, null).getPropertyValue('opacity'); hasOpacity = true; } if (hasOpacity === false) { return 1.0; } return parseFloat(opacity); }, setElementOpacity : function(element, value) { /// /// Set the element's opacity /// /// /// Element /// /// /// Opacity of the element /// if (!element) { throw Error.argumentNull('element'); } 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; } }, resolveFunction : function(value) { /// /// Returns a function reference that corresponds to the provided value /// /// /// The value can either be a Function, the name of a function (that can be found using window['name']), /// or an expression that evaluates to a function. /// /// /// Reference to the function, or null if not found /// if (value) { if (value instanceof Function) { return value; } else if (String.isInstanceOfType(value) && value.length > 0) { var func; if ((func = window[value]) instanceof Function) { return func; } else if ((func = eval(value)) instanceof Function) { return func; } } } return null; }, addCssClasses : function(element, classNames) { /// /// Adds multiple css classes to a DomElement /// /// The element to modify /// The class names to add for(var i = 0; i < classNames.length; i++) { Sys.UI.DomElement.addCssClass(element, classNames[i]); } }, removeCssClasses : function(element, classNames) { /// /// Removes multiple css classes to a DomElement /// /// The element to modify /// The class names to remove for(var i = 0; i < classNames.length; i++) { Sys.UI.DomElement.removeCssClass(element, classNames[i]); } }, setStyle : function(element, style) { /// /// Sets the style of the element using the supplied style template object /// /// The element to modify /// The template $common.applyProperties(element.style, style); }, removeHandlers : function(element, events) { /// /// Removes a set of event handlers from an element /// /// The element to modify /// The template object that contains event names and delegates /// /// This is NOT the same as $clearHandlers which removes all delegates from a DomElement. This rather removes select delegates /// from a specified element and has a matching signature as $addHandlers /// for (var name in events) { $removeHandler(element, name, events[name]); } }, containsPoint : function(rect, x, y) { /// /// Tests whether a point (x,y) is contained within a rectangle /// /// The rectangle /// The x coordinate of the point /// The y coordinate of the point return x >= rect.x && x <= (rect.x + rect.width) && y >= rect.y && y <= (rect.y + rect.width); }, isKeyDigit : function(keyCode) { /// /// Gets whether the supplied key-code is a digit /// /// The key code of the event (from Sys.UI.DomEvent) /// return (0x30 <= keyCode && keyCode <= 0x39); }, isKeyNavigation : function(keyCode) { /// /// Gets whether the supplied key-code is a navigation key /// /// The key code of the event (from Sys.UI.DomEvent) /// return (Sys.UI.Key.left <= keyCode && keyCode <= Sys.UI.Key.down); }, padLeft : function(text, size, ch, truncate) { /// /// Pads the left hand side of the supplied text with the specified pad character up to the requested size /// /// The text to pad /// The size to pad the text (default is 2) /// The single character to use as the pad character (default is ' ') /// Whether to truncate the text to size (default is false) return AjaxControlToolkit.CommonToolkitScripts._pad(text, size || 2, ch || ' ', 'l', truncate || false); }, padRight : function(text, size, ch, truncate) { /// /// Pads the right hand side of the supplied text with the specified pad character up to the requested size /// /// The text to pad /// The size to pad the text (default is 2) /// The single character to use as the pad character (default is ' ') /// Whether to truncate the text to size (default is false) return AjaxControlToolkit.CommonToolkitScripts._pad(text, size || 2, ch || ' ', 'r', truncate || false); }, _pad : function(text, size, ch, side, truncate) { /// /// Pads supplied text with the specified pad character up to the requested size /// /// The text to pad /// The size to pad the text /// The single character to use as the pad character /// Either 'l' or 'r' to siginfy whether to pad the Left or Right side respectively /// Whether to truncate the text to size text = text.toString(); var length = text.length; var builder = new Sys.StringBuilder(); if (side == 'r') { builder.append(text); } while (length < size) { builder.append(ch); length++; } if (side == 'l') { builder.append(text); } var result = builder.toString(); if (truncate && result.length > size) { if (side == 'l') { result = result.substr(result.length - size, size); } else { result = result.substr(0, size); } } return result; }, applyProperties : function(target, properties) { /// /// Quick utility method to copy properties from a template object to a target object /// /// The object to apply to /// The template to copy values from for (var p in properties) { var pv = properties[p]; if (Object.getType(pv)===Object) { var tv = target[p]; AjaxControlToolkit.CommonToolkitScripts.applyProperties(tv, pv); } else { target[p] = pv; } } }, createElementFromTemplate : function(template, appendToParent) { /// /// Creates an element for the current document based on a template object /// /// The template from which to create the element /// A DomElement under which to append this element /// /// /// This method is useful if you find yourself using the same or similar DomElement constructions throughout a class. You can even set the templates /// as static properties for a type to cut down on overhead. This method is often called with a JSON style template: /// /// var elt = $common.createElementFromTemplate({ /// nodeName : "div", /// properties : { /// style : { /// height : "100px", /// width : "100px", /// backgroundColor : "white" /// }, /// expandoAttribute : "foo" /// }, /// events : { /// click : function() { alert("foo"); }, /// mouseover : function() { elt.backgroundColor = "silver"; }, /// mouseout : function() { elt.backgroundColor = "white"; } /// }, /// cssClasses : [ "class0", "class1" ], /// visible : true, /// opacity : .5 /// }, someParent); /// /// var elt = document.createElement(template.nodeName); if (typeof(template.properties)!=='undefined') AjaxControlToolkit.CommonToolkitScripts.applyProperties(elt, template.properties); if (typeof(template.cssClasses)!=='undefined') AjaxControlToolkit.CommonToolkitScripts.addCssClasses(elt, template.cssClasses); if (typeof(template.events)!=='undefined') $addHandlers(elt, template.events); if (typeof(template.visible)!=='undefined') Sys.UI.DomElement.setVisible(elt, template.visible); if (appendToParent) appendToParent.appendChild(elt); if (typeof(template.opacity)!=='undefined') AjaxControlToolkit.CommonToolkitScripts.setElementOpacity(elt, template.opacity); return elt; } } // Create the singleton instance of the CommonToolkitScripts var CommonToolkitScripts = AjaxControlToolkit.CommonToolkitScripts = new AjaxControlToolkit._CommonToolkitScripts(); var $common = CommonToolkitScripts; AjaxControlToolkit._DomUtility = function() { /// /// Utility functions for manipulating the DOM /// } AjaxControlToolkit._DomUtility.prototype = { isDescendant : function(ancestor, descendant) { /// /// Whether the specified element is a descendant of the ancestor /// /// Ancestor node /// Possible descendant node /// for (var n = descendant.parentNode; n != null; n = n.parentNode) { if (n == ancestor) return true; } return false; }, isDescendantOrSelf : function(ancestor, descendant) { /// /// Whether the specified element is a descendant of the ancestor or the same as the ancestor /// /// Ancestor node /// Possible descendant node /// if (ancestor === descendant) return true; return AjaxControlToolkit.DomUtility.isDescendant(ancestor, descendant); }, isAncestor : function(descendant, ancestor) { /// /// Whether the specified element is an ancestor of the descendant /// /// Descendant node /// Possible ancestor node /// return AjaxControlToolkit.DomUtility.isDescendant(ancestor, descendant); }, isAncestorOrSelf : function(descendant, ancestor) { /// /// Whether the specified element is an ancestor of the descendant or the same as the descendant /// /// Descendant node /// Possible ancestor node /// if (descendant === ancestor) return true; return AjaxControlToolkit.DomUtility.isDescendant(ancestor, descendant); }, isSibling : function(self, sibling) { /// /// Whether the specified element is a sibling of the self element /// /// Self node /// Possible sibling node /// var parent = self.parentNode; for (var i = 0; i < parent.childNodes.length; i++) { if (parent.childNodes[i] == sibling) return true; } return false; } } AjaxControlToolkit._DomUtility.registerClass("AjaxControlToolkit._DomUtility"); AjaxControlToolkit.DomUtility = new AjaxControlToolkit._DomUtility(); if(typeof(Sys)!=='undefined')Sys.Application.notifyScriptLoaded();