/// <summary> /// Set fyout coordinates given information about the viewing area in the screen, the launching control and the flyout dimensions. /// </summary> /// <param name="flyOut">The flyout to be launched.</param> /// <param name="dimensions">Position information on the screen viewing area, lauching control and flyout.</param> internal void SetFlyOutCoordinates(HtmlElement flyOut, Dictionary<string, int> dimensions, bool horizontal) { // reusable boolean to check whether the dom element must be edited or not bool changed = false; if (CUIUtility.IsNullOrUndefined(flyOut) || CUIUtility.IsNullOrUndefined(dimensions)) { return; } // Create default coordinates int flyOutLeft; int flyOutTop; // Cache dimensions for performance int launcherLeft = dimensions["launcherLeft"]; int launcherTop = dimensions["launcherTop"]; int launcherWidth = dimensions["launcherWidth"]; int launcherHeight = dimensions["launcherHeight"]; int flyOutWidth = dimensions["flyOutWidth"]; int flyOutHeight = dimensions["flyOutHeight"]; int flyOutRealHeight = dimensions["flyOutRealHeight"]; int viewportWidth = dimensions["viewportWidth"]; int viewportHeight = dimensions["viewportHeight"]; int viewableLeft = dimensions["viewableLeft"]; int viewableTop = dimensions["viewableTop"]; bool isLTR = Root.TextDirection == Direction.LTR; bool buttedToRightEdge = false, buttedToLeftEdge = false; string objScrollable = flyOut.GetAttribute("mscui:scrollable"); bool wasScrollable = Utility.IsTrue(objScrollable); if (horizontal) { if (isLTR) { // Left-to-right method flyOutLeft = launcherLeft + launcherWidth; flyOutLeft += 2; // styling: make the borders of the menus align } else // Right-to-left method { flyOutLeft = launcherLeft - flyOutWidth; } flyOutTop = launcherTop; } else { if (isLTR) { // Left-to-right method flyOutLeft = launcherLeft; } else // Right-to-left method { flyOutLeft = launcherLeft + launcherWidth - flyOutWidth; } flyOutTop = launcherTop + launcherHeight; int minWidth = launcherWidth >= 2 ? launcherWidth - 2 : launcherWidth /* borders */; // O14:389872 - flyout should be at least as wide as the launcher if (minWidth > flyOutWidth) flyOutWidth = minWidth; flyOut.Style.MinWidth = minWidth + "px"; } // If the root is fixed positioned, then we need to take scroll offset into account (O14:28297) if (FixedPositioningEnabled) { flyOutTop += viewableTop; flyOutLeft += viewableLeft; } flyOut.Style.Top = flyOutTop + "px"; flyOut.Style.Left = flyOutLeft + "px"; // Horizonal Positioning // If the flyOut can fit in the viewport at all, then try positioning logic if (flyOutWidth <= viewportWidth) { // If the flyOut is too close to the right side of the viewport if (flyOutLeft + flyOutWidth > viewableLeft + viewportWidth) { // If we're positioning horizontally and the flyout can fit // launching the other way, try that if (horizontal && isLTR && (launcherLeft - flyOutWidth) > viewableLeft) { flyOutLeft = launcherLeft - flyOutWidth; } // Otherwise, just align along the edge of the viewport else { flyOutLeft = viewableLeft + viewportWidth - flyOutWidth - 5; buttedToRightEdge = true; } changed = true; } // If the flyOut is too close to the left side of the viewport else if (flyOutLeft < viewableLeft) { // If we're positioning horizontally and the flyout can fit // launching the other way, try that if (horizontal && !isLTR && (launcherLeft + launcherWidth + flyOutWidth) < (viewableLeft + viewportWidth)) { flyOutLeft = launcherLeft + launcherWidth; } // Otherwise, just align along the edge of the viewport else { flyOutLeft = viewableLeft + 5; buttedToLeftEdge = true; } changed = true; } else { changed = false; } } // If the flyOut can't fit into the viewport, just align against the appropriate edge else { if (isLTR) { flyOutLeft = viewableLeft; changed = true; } else // RTL { flyOutLeft = viewableLeft + viewportWidth - flyOutWidth; changed = true; } } // If changed, set the styles accordingly if (changed) { flyOut.Style.Left = flyOutLeft + "px"; changed = false; } // Vertical Positioning (not affected by Text Direction) // If the flyOut is too close to the bottom of the viewport, launch the flyOut upwards // We work with the real height of the flyout's content here so that even if it is // currently scrollable, we can see if it still needs to be scrollable if (flyOutTop + flyOutRealHeight > viewableTop + viewportHeight) { // store initial value and viewableHeight int oldflyOutTop = flyOutTop; int oldflyOutViewableHeight = viewableTop + viewportHeight - flyOutTop; flyOutTop = launcherTop - flyOutRealHeight; if (FixedPositioningEnabled) flyOutTop += viewableTop; int newflyOutViewableHeight = launcherTop; if (!FixedPositioningEnabled) newflyOutViewableHeight -= viewableTop; changed = true; // If launching upwards is worse than before, go back to launching downwards if (newflyOutViewableHeight < flyOutRealHeight) { int flyOutWidthWithScrollbar = flyOutWidth + 22; if (newflyOutViewableHeight < oldflyOutViewableHeight) { flyOutTop = oldflyOutTop; // O14:45827 - Enable scrolling and change the height of the menu to fit in the space available flyOut.Style.MaxHeight = (oldflyOutViewableHeight - 5) + "px"; if (!wasScrollable) { flyOut.Style.OverflowY = "scroll"; flyOut.Style.Width = flyOutWidthWithScrollbar + "px"; } if (buttedToRightEdge && isLTR) { flyOutLeft -= 27; // compensate for the added scrollbar flyOut.Style.Left = flyOutLeft + "px"; } else if (buttedToLeftEdge && !isLTR) { flyOutLeft += 27; // compensate for the added scrollbar flyOut.Style.Left = flyOutLeft + "px"; } changed = false; } else { // Can't fit in either direction, but launching upwards is better // Still need to resize the menu and enable scrolling flyOut.Style.MaxHeight = (newflyOutViewableHeight - 5) + "px"; if (!wasScrollable) { flyOut.Style.OverflowY = "scroll"; flyOut.Style.Width = flyOutWidthWithScrollbar + "px"; } if (buttedToRightEdge && isLTR) { flyOutLeft -= 27; // compensate for the added scrollbar flyOut.Style.Left = flyOutLeft + "px"; } else if (buttedToLeftEdge && !isLTR) { flyOutLeft += 27; // compensate for the added scrollbar flyOut.Style.Left = flyOutLeft + "px"; } } if (!wasScrollable) flyOut.SetAttribute("mscui:scrollable", "true"); } else // fits fine when launching upwards { // Revert auto-scroll styles to default if not needed if (wasScrollable) { flyOut.Style.MaxHeight = "none"; flyOut.Style.OverflowY = "visible"; flyOut.Style.Width = "auto"; flyOut.SetAttribute("mscui:scrollable", "false"); } } } else // fits fine vertically { // Revert auto-scroll styles to default if not needed if (wasScrollable) { flyOut.Style.MaxHeight = "none"; flyOut.Style.OverflowY = "visible"; flyOut.Style.Width = "auto"; flyOut.SetAttribute("mscui:scrollable", "false"); } changed = false; } // If changed, set the styles accordingly if (changed) { flyOut.Style.Top = flyOutTop + "px"; changed = false; } }
/// <summary> /// Sets the Aria 'describedby' attribute for controls that have a SuperToolTip defined. /// </summary> /// <remarks> /// The 'aria-describedby' attribute points to the SuperToolTip defined for this control. It is used by Assistive Technologies to indicate /// the DOM element containing more information on the selected control. /// </remarks> /// <param name="properties">The control's properties.</param> /// <param name="focusElement">The element of the control that recieves focus when the control is selected.</param> internal static void SetAriaTooltipProperties(ControlProperties properties, HtmlElement focusElement) { if (!CUIUtility.IsNullOrUndefined(properties) && !CUIUtility.IsNullOrUndefined(focusElement) && !string.IsNullOrEmpty(properties.ToolTipTitle)) focusElement.SetAttribute("aria-describedby", properties.Id + "_ToolTip"); }
/// <summary> /// Make a link so that it will not navigate the page anywhere when it is invoked. /// </summary> /// <param name="element"></param> internal static void NoOpLink(HtmlElement element) { element.SetAttribute("href", "javascript:;"); element.SetAttribute("onclick", "return false;"); }
// Because right now we always want to set nearly everything to unselectable // and to suppress the context menu, I'm overloading this to do them both. // If we need to separate them in the future, then we can add an additional // argument to this function or split it out into its own function. internal static void SetUnselectable(HtmlElement element, bool on, bool recursive) { // Apparently text nodes do not have an "unselectable" property. if (CUIUtility.IsNullOrUndefined(element) || string.Compare(element.NodeName.ToLower(), "#text") == 0) return; if (on) element.SetAttribute("unselectable", "on"); else element.SetAttribute("unselectable", "off"); if (recursive) { DomNode p = element.FirstChild; while (p != null) { SetUnselectable((HtmlElement)p, on, true); p = p.NextSibling; } } }
protected override HtmlElement CreateDOMElementForDisplayMode(string displayMode) { string forId = Properties.ForId; string label = Properties.LabelText; switch (displayMode) { case "Medium": if (!string.IsNullOrEmpty(forId)) { _elmDefault = new MSLabel(); if (BrowserUtility.InternetExplorer7) { _elmDefault.SetAttribute("htmlFor", forId); } else { _elmDefault.SetAttribute("for", forId); } } else { _elmDefault = new Span(); } _elmDefault.SetAttribute("mscui:controltype", ControlType); _elmDefault.ClassName = "ms-cui-ctl-small ms-cui-fslb"; if (!string.IsNullOrEmpty(Properties.Image16by16)) { _elmDefaultIcon = new Image(); Span elmDefaultIconCont = Utility.CreateClusteredImageContainerNew( ImgContainerSize.Size16by16, Properties.Image16by16, Properties.Image16by16Class, _elmDefaultIcon, true, false, Properties.Image16by16Top, Properties.Image16by16Left); Span elmDefaultIconContainer = new Span(); elmDefaultIconContainer.ClassName = "ms-cui-ctl-iconContainer"; elmDefaultIconContainer.AppendChild(elmDefaultIconCont); _elmDefault.AppendChild(elmDefaultIconContainer); } _elmDefaultLabel = new Span(); _elmDefaultLabel.ClassName = "ms-cui-ctl-mediumlabel"; if (!string.IsNullOrEmpty(label)) { UIUtility.SetInnerText(_elmDefaultLabel, label); } _elmDefault.AppendChild(_elmDefaultLabel); return _elmDefault; case "Small": if (!string.IsNullOrEmpty(forId)) { _elmSmall = new MSLabel(); if (BrowserUtility.InternetExplorer7) { _elmSmall.SetAttribute("htmlFor", forId); } else { _elmSmall.SetAttribute("for", forId); } } else { _elmSmall = new Span(); } _elmSmall.SetAttribute("mscui:controltype", ControlType); _elmSmall.ClassName = "ms-cui-ctl-small ms-cui-fslb"; if (string.IsNullOrEmpty(Properties.Image16by16)) { throw new ArgumentNullException("Image16by16", "Small display mode must have an icon set"); } _elmSmallIcon = new Image(); Span elmSmallIconCont = Utility.CreateClusteredImageContainerNew( ImgContainerSize.Size16by16, Properties.Image16by16, Properties.Image16by16Class, _elmSmallIcon, true, false, Properties.Image16by16Top, Properties.Image16by16Left); if (!string.IsNullOrEmpty(label)) { _elmSmallIcon.Alt = label; } Span elmSmallIconContainer = new Span(); elmSmallIconContainer.ClassName = "ms-cui-ctl-iconContainer"; elmSmallIconContainer.AppendChild(elmSmallIconCont); _elmSmall.AppendChild(elmSmallIconContainer); return _elmSmall; default: EnsureValidDisplayMode(displayMode); break; } return null; }