// (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('Microsoft.Mtps.Rendering.Behaviors.Ajax');
Microsoft.Mtps.Rendering.Behaviors.Ajax.BoxSide = function() {
///
/// The BoxSide enumeration describes the sides of a DOM element
///
///
///
///
///
}
Microsoft.Mtps.Rendering.Behaviors.Ajax.BoxSide.prototype = {
Top : 0,
Right : 1,
Bottom : 2,
Left : 3
}
Microsoft.Mtps.Rendering.Behaviors.Ajax.BoxSide.registerEnum("Microsoft.Mtps.Rendering.Behaviors.Ajax.BoxSide", false);
Microsoft.Mtps.Rendering.Behaviors.Ajax._CommonToolkitScripts = function() {
///
/// The _CommonToolkitScripts class contains functionality utilized across a number
/// of controls (but not universally)
///
// 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;
}
Microsoft.Mtps.Rendering.Behaviors.Ajax._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).
///
///
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
///
///
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 actual location of an element.
///
///
/// Gets the top/left distance from the top/left corner of the browser window.
/// Overcomes offsetTop/Left calculation issues in IE5+.
///
/// DOM element
/// Location (of the form {x,y}) with respect to the top/left corner
if (!element) {
throw Error.argumentNull('element');
}
var offsetX = element.offsetLeft;
var offsetY = element.offsetTop;
var parent;
var tdLeftBorderFound;
var tdTopBorderFound;
var leftBorderThickness;
var topBorderThickness;
var defaultTdLeftBorderFound;
var defaultTdTopBorderFound;
for (parent = element.offsetParent; parent; parent = parent.offsetParent) {
if (Sys.Browser.agent == Sys.Browser.InternetExplorer && parent.nodeName != 'BODY') {
if(parent.nodeName == 'TD' && parent.currentStyle.borderLeftStyle == 'inset' && parent.currentStyle.borderLeftWidth == 'medium') {
defaultTdLeftBorderFound = true;
}
if(parent.nodeName == 'TD' && parent.currentStyle.borderTopStyle == 'inset' && parent.currentStyle.borderTopWidth == 'medium') {
defaultTdTopBorderFound = true;
}
if(parent.nodeName == 'TABLE') {
if(parent.rules == "all") {
var mediumThickness = this.parseBorderWidth("medium");
if(defaultTdLeftBorderFound) offsetX -= mediumThickness - 1;
if(defaultTdTopBorderFound) offsetY -= mediumThickness - 1;
}
if(parent.currentStyle.borderCollapse == 'collapse') {
if(tdLeftBorderFound && !defaultTdLeftBorderFound && leftBorderThickness > 1) offsetX --;
if(tdTopBorderFound && !defaultTdTopBorderFound && topBorderThickness > 1) offsetY --;
}
tdTopBorderFound = false;
tdLeftBorderFound = false;
defaultTdLeftBorderFound = false;
defaultTdTopBorderFound = false;
}
if(this.isBorderVisible(parent, Microsoft.Mtps.Rendering.Behaviors.Ajax.BoxSide.Left)) {
if(parent.nodeName == 'TD') tdLeftBorderFound = true;
offsetX += leftBorderThickness = this.getBorderWidth(parent, Microsoft.Mtps.Rendering.Behaviors.Ajax.BoxSide.Left);
}
if(this.isBorderVisible(parent, Microsoft.Mtps.Rendering.Behaviors.Ajax.BoxSide.Top)) {
if(parent.nodeName == 'TD') tdTopBorderFound = true;
offsetY += topBorderThickness = this.getBorderWidth(parent, Microsoft.Mtps.Rendering.Behaviors.Ajax.BoxSide.Top);
}
}
if (parent.offsetLeft) {
offsetX += parent.offsetLeft;
}
if (parent.offsetTop) {
offsetY += parent.offsetTop;
}
if (parent.nodeName != 'BODY' && parent.nodeName != 'HTML') {
if (parent.scrollLeft) {
offsetX -= parent.scrollLeft;
}
if (parent.scrollTop) {
offsetY -= parent.scrollTop;
}
}
}
return { x : offsetX, y : offsetY };
},
setLocation : function(element, point) {
///
/// Sets the current location for an element.
///
///
/// 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.
///
/// DOM element
/// Point object (of the form {x,y})
///
if (!element) {
throw Error.argumentNull('element');
}
if (!point) {
throw Error.argumentNull('point');
}
element.style.left = point.x.toString() + 'px';
element.style.top = point.y.toString() + 'px';
},
getContentSize : function(element) {
///
/// Gets the "content-box" size of an element.
///
///
/// 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.
///
/// DOM element
/// Size of the element (in the form {width,height})
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.
///
///
/// 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');
}
return {
width: element.offsetWidth,
height: element.offsetHeight
};
},
setContentSize : function(element, size) {
///
/// Sets the "content-box" size of an element.
///
///
/// 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.
///
/// DOM element
/// Size of the element (in the form {width,height})
///
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 "border-box" bounds 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
///
/// Bounds of the element (of the form
/// {x,y,width,height,right,bottom,location:{x,y},size:{width,height}})
///
if (!element) {
throw Error.argumentNull('element');
}
var location = this.getLocation(element);
var size = this.getSize(element);
return {
x: location.x,
y: location.y,
width: size.width,
height: size.height,
right: location.x + size.width,
bottom: location.y + size.height,
location: location,
size: size
};
},
setBounds : function(element, bounds) {
///
/// Sets the "border-box" bounds 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
/// Bounds of the element (of the form {x,y,width,height})
///
if (!element) {
throw Error.argumentNull('element');
}
if (!bounds) {
throw Error.argumentNull('bounds');
}
this.setSize(element, bounds);
this.setLocation(element, bounds);
},
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, Microsoft.Mtps.Rendering.Behaviors.Ajax.BoxSide.Top),
right: this.getBorderWidth(element, Microsoft.Mtps.Rendering.Behaviors.Ajax.BoxSide.Right),
bottom: this.getBorderWidth(element, Microsoft.Mtps.Rendering.Behaviors.Ajax.BoxSide.Bottom),
left: this.getBorderWidth(element, Microsoft.Mtps.Rendering.Behaviors.Ajax.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, Microsoft.Mtps.Rendering.Behaviors.Ajax.BoxSide.Top),
right: this.getPadding(element, Microsoft.Mtps.Rendering.Behaviors.Ajax.BoxSide.Right),
bottom: this.getPadding(element, Microsoft.Mtps.Rendering.Behaviors.Ajax.BoxSide.Bottom),
left: this.getPadding(element, Microsoft.Mtps.Rendering.Behaviors.Ajax.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 < Microsoft.Mtps.Rendering.Behaviors.Ajax.BoxSide.Top || boxSide > Microsoft.Mtps.Rendering.Behaviors.Ajax.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 < Microsoft.Mtps.Rendering.Behaviors.Ajax.BoxSide.Top || boxSide > Microsoft.Mtps.Rendering.Behaviors.Ajax.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 < Microsoft.Mtps.Rendering.Behaviors.Ajax.BoxSide.Top || boxSide > Microsoft.Mtps.Rendering.Behaviors.Ajax.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
///
/// borderWidth is String ('thin','medium','thick','inherit',,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);
// 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',,null,'')
/// Number of pixels in the padding
if(padding) {
if(padding == 'inherit') {
return 0;
}
var unit = this.parseUnit(padding);
// 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 ,<% 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;
}
}
// Create the singleton instance of the CommonToolkitScripts
var CommonToolkitScripts = Microsoft.Mtps.Rendering.Behaviors.Ajax.CommonToolkitScripts = new Microsoft.Mtps.Rendering.Behaviors.Ajax._CommonToolkitScripts();
if(typeof(Sys)!=='undefined')Sys.Application.notifyScriptLoaded();