AdfRichUIPeer.createPeerClass(AdfRichUIPeer, "AdfDhtmlMenuPeer", false);
AdfDhtmlMenuPeer.InitSubclass = function() {
  AdfObject.ensureClassInitialization(AdfMenuUtils);
  AdfObject.ensureClassInitialization(AdfSwipeSupport);
  AdfRichUIPeer.addComponentEventHandlers(this, AdfUIInputEvent.MOUSE_DOWN_EVENT_TYPE, AdfUIInputEvent.MOUSE_UP_EVENT_TYPE, AdfUIInputEvent.FOCUS_EVENT_TYPE, AdfUIInputEvent.BLUR_EVENT_TYPE, AdfUIInputEvent.KEY_UP_EVENT_TYPE, AdfUIInputEvent.KEY_DOWN_EVENT_TYPE, AdfUIInputEvent.KEY_PRESS_EVENT_TYPE);
  if (!AdfAgent.AGENT.isTouchFirstDevice()) {
    AdfRichUIPeer.addComponentEventHandlers(this, AdfUIInputEvent.MOUSE_IN_EVENT_TYPE, AdfUIInputEvent.MOUSE_OUT_EVENT_TYPE);
  }
  AdfRichUIPeer.addComponentPropertyChanges(this, AdfRichMenu.DISABLED, AdfRichMenu.VISIBLE, AdfRichMenu.TEXT);
  this._sBarMenus = [];
  this._sDetachedMenus = [];
  this._SCROLL_DELTA = 3;
  this._JUMP_SCROLL_DELTA = 15;
  this._OPEN_CLOSE_DELAY = 300;
  var keyCode = AdfKeyStroke.M_KEY;
  var modifiers = AdfKeyStroke.SHIFT_MASK | AdfKeyStroke.CTRL_MASK;
  this._menuBarKeyStroke = AdfKeyStroke.getKeyStroke(keyCode, modifiers);
  keyCode = AdfKeyStroke.W_KEY;
  modifiers = AdfKeyStroke.SHIFT_MASK | AdfKeyStroke.CTRL_MASK;
  this._focusDetachedMenuKeyStroke = AdfKeyStroke.getKeyStroke(keyCode, modifiers);
};
AdfDhtmlMenuPeer.prototype.Init = function(component) {
  component.getParent();
  AdfDhtmlMenuPeer.superclass.Init.call(this, component);
  var lookAndFeel = AdfPage.PAGE.getLookAndFeel();
  var skinVisibileItems = parseInt(lookAndFeel.getSkinProperty("af|menu-tr-visible-items"));
  this._maxDisplayItems = isNaN(skinVisibileItems) ? 14 : skinVisibileItems;
  this._isDetached = false;
  this._enterKeyDown = false;
  this._spaceKeyDown = false;
};
AdfDhtmlMenuPeer.prototype.InitDomElement = function(component, domElement) {
  if (domElement.getAttribute(AdfMenuUtils.MENU_DEPTH_KEY) == "1") {
    var clientId = component.getClientId();
    AdfDhtmlMenuPeer._addBarMenu(clientId);
  }
};
AdfDhtmlMenuPeer.cancelShowing = function() {
  if (AdfDhtmlMenuPeer._popupShowingHandle) {
    window.clearTimeout(AdfDhtmlMenuPeer._popupShowingHandle);
    delete AdfDhtmlMenuPeer._popupShowingHandle;
    delete AdfDhtmlMenuPeer._popupPeerWaitingForShow;
  }
};
AdfDhtmlMenuPeer.prototype.show = function(popupHints, focusOnFirstElement) {
  var rootElement = this.getDomElement();
  var component = this.getComponent();
  var clientId = component.getClientId();
  AdfDomUtils.addCSSClassName(rootElement, AdfMenuUtils.HIGHLIGHTED_STYLE_CLASS);
  if (!this.isContextMenu() && this.isRootMenu()) {
    AdfMenuUtils.setLastOpenedRootMenuId(clientId);
  }
  if (focusOnFirstElement == null && popupHints != null) {
    var popupFocusHint = popupHints[AdfDhtmlPopupHints.FOCUS];
    if (popupFocusHint != null) {
      focusOnFirstElement = popupFocusHint;
    } else {
      focusOnFirstElement = this.isContextMenu() ? true : false;
    }
  }
  this._reattachMenu();
  if (this._getLazyState() == "noContent") {
    this._setLazyState("fetching");
    var params = new Object;
    params.menuDepth = this._getDepth();
    this._lazyFetchPopupHints = popupHints;
    this._lazyFetchFocusOnFirstElement = focusOnFirstElement;
    (new AdfContentFetchEvent(component, AdfContentFetchEvent.FETCH_EVENT_TYPE, params)).queue();
    this._showFetchingDataPopup();
    return;
  } else {
    if (this._getLazyState() == "fetching") {
      AdfLogger.LOGGER.info("Currently waiting on menu content fetch: " + component.getClientId());
      return;
    }
  }
  var menuElement = this._getMenuElement();
  if (menuElement.style.display == "block") {
    var agent = AdfAgent.AGENT;
    var domWindow = agent.getDomWindow();
    if (domWindow.AdfSafariMobileAgent && agent instanceof AdfSafariMobileAgent) {
      AdfFocusUtils.focusPreviousTabStop(menuElement);
    } else {
      if (focusOnFirstElement) {
        AdfFocusUtils.focusElement(this._activeDescendant);
      }
    }
    return;
  }
  this.resetActiveDescendant();
  var hints = this._createMenuPopupHints(popupHints, focusOnFirstElement);
  menuElement.style.display = "block";
  var elemsInitialized = this._elemsInitialized;
  if (!elemsInitialized) {
    menuElement.style.visibility = "hidden";
  }
  this.showPopup(component, menuElement, hints, clientId);
  if (!elemsInitialized) {
    this._initElements(component, clientId, menuElement);
    menuElement.style.visibility = "";
    this._elemsInitialized = true;
    if (this._areScrollButtonsDisplayed) {
      this._moveShadow(true);
    }
  }
  if (this._areScrollButtonsDisplayed) {
    this.updateScrollIconsState();
  }
  if (this._isDetachable()) {
    this._createDetachableWindow();
  }
};
AdfDhtmlMenuPeer.prototype.showPopup = function(component, element, hints, popupId) {
  AdfMenuUtils.addOpenMenu(popupId);
  AdfDhtmlMenuPeer.superclass.showPopup.call(this, component, element, hints, popupId);
};
AdfDhtmlMenuPeer.prototype.hidePopup = function() {
  var component = this.getComponent();
  var clientId = component.getClientId();
  if (clientId == AdfDhtmlMenuPeer._reattachedMenuId) {
    AdfDhtmlMenuPeer._redetachMenu();
  }
  if (!this.isDetached()) {
    this._handleHideRequest(component, clientId);
    AdfDhtmlMenuPeer.superclass.hidePopup.call(this, component, clientId);
    if (this._isDetachable()) {
      if (this._detachableWindow) {
        this._detachableWindow.destroy();
      }
      delete this._detachableWindow;
    }
  }
};
AdfDhtmlMenuPeer.prototype.cancelPopup = function() {
  var component = this.getComponent();
  var clientId = component.getClientId();
  if (this.isDetached()) {
    if (clientId == AdfDhtmlMenuPeer._reattachedMenuId) {
      AdfDhtmlMenuPeer._redetachMenu();
    }
    return;
  }
  this._handleHideRequest(component, clientId);
  AdfLogger.LOGGER.finest("menuBar auto open mode, set to OFF due to cancel popup event");
  AdfMenuUtils.setMenuBarAutoOpenMode(false);
  AdfDhtmlMenuPeer.superclass.cancelPopup.call(this, component, clientId);
};
AdfDhtmlMenuPeer.prototype.close = function(immediate, keepSelectedStyle) {
  var component = this.getComponent();
  if (this.isDetached()) {
    AdfDomUtils.addCSSClassName(this._getMenuElement(), AdfMenuUtils.DETACHED_STYLE_CLASS);
    if (this._detachedMenuLeft && this._detachedMenuTop) {
      var floatingElement = this._detachableWindow.getElement();
      floatingElement.style.left = this._detachedMenuLeft;
      floatingElement.style.top = this._detachedMenuTop;
    }
    if (!keepSelectedStyle) {
      this._deselectElement();
    }
    var clientId = component.getClientId();
    AdfDhtmlMenuPeer._removeFromDetachedMenus(clientId);
    AdfDhtmlMenuPeer.superclass.hidePopup.call(this, component, clientId);
    return;
  }
  if (this.isContextMenu()) {
    var parent = component.getParent();
    parent.hide();
  } else {
    if (immediate) {
      this.hidePopup();
    } else {
      this._delayPopupHiding();
    }
    if (!keepSelectedStyle) {
      this._deselectElement();
    }
  }
};
AdfDhtmlMenuPeer.prototype.isDetached = function() {
  return this._isDetached;
};
AdfDhtmlMenuPeer.prototype.isContextMenu = function() {
  var component = this.getComponent();
  return component.getParent() instanceof AdfRichPopup;
};
AdfDhtmlMenuPeer.prototype.isRootMenu = function() {
  return this._getDepth() == 1;
};
AdfDhtmlMenuPeer.prototype.updateScrollIconsState = function() {
  if (this._areScrollButtonsDisplayed) {
    var menuItems = this._scrollContentElement.rows;
    var n = menuItems.length;
    var topItemIndex = 0;
    var bottomItemIndex = 0;
    for (var i = 0;i < n;i++) {
      var menuItem = menuItems[i];
      if (menuItem.style.display != "none") {
        topItemIndex = i;
        break;
      }
    }
    for (var i = n - 1;i > -1;i--) {
      var menuItem = menuItems[i];
      if (menuItem.style.display != "none") {
        bottomItemIndex = i;
        break;
      }
    }
    var agent = AdfAgent.AGENT;
    var isAtScrollTop = false;
    var isAtScrollBottom = false;
    var containerBox = agent.getElementPageBounds(this._scrollBoxElement);
    var topItemBox = agent.getElementPageBounds(menuItems[topItemIndex]);
    var bottomItemBox = agent.getElementPageBounds(menuItems[bottomItemIndex]);
    var bottomItemVisibleHeight = containerBox["bottom"] - bottomItemBox["top"];
    var bottomItemHeight = bottomItemBox["bottom"] - bottomItemBox["top"];
    isAtScrollBottom = bottomItemVisibleHeight / bottomItemHeight * 100 >= 90;
    var topItemVisibleHeight = topItemBox["bottom"] - containerBox["top"];
    var topItemHeight = topItemBox["bottom"] - topItemBox["top"];
    isAtScrollTop = topItemVisibleHeight / topItemHeight * 100 >= 90;
    var scrollBoxElement = this._scrollBoxElement;
    var scrollTop = scrollBoxElement.scrollTop;
    var offsetHeight = scrollBoxElement.offsetHeight;
    var scrollHeight = scrollBoxElement.scrollHeight;
    if (isAtScrollTop) {
      AdfDomUtils.addCSSClassName(this._scrollUpElement, AdfRichUIPeer.DISABLED_STYLECLASS);
      AdfDomUtils.addCSSClassName(this._scrollUpBackgroundElement, AdfRichUIPeer.DISABLED_STYLECLASS);
    } else {
      AdfDomUtils.removeCSSClassName(this._scrollUpElement, AdfRichUIPeer.DISABLED_STYLECLASS);
      AdfDomUtils.removeCSSClassName(this._scrollUpBackgroundElement, AdfRichUIPeer.DISABLED_STYLECLASS);
    }
    if (isAtScrollBottom) {
      AdfDomUtils.addCSSClassName(this._scrollDownElement, AdfRichUIPeer.DISABLED_STYLECLASS);
      AdfDomUtils.addCSSClassName(this._scrollDownBackgroundElement, AdfRichUIPeer.DISABLED_STYLECLASS);
    } else {
      AdfDomUtils.removeCSSClassName(this._scrollDownElement, AdfRichUIPeer.DISABLED_STYLECLASS);
      AdfDomUtils.removeCSSClassName(this._scrollDownBackgroundElement, AdfRichUIPeer.DISABLED_STYLECLASS);
    }
  }
};
AdfDhtmlMenuPeer.prototype.resetActiveDescendant = function() {
  if (this._activeDescendant) {
    this._activeDescendant.setAttribute("tabIndex", "-1");
  }
  var menuElement = this._getMenuElement();
  var context = {includeVisibilityHidden:true, includeDisplayNone:true};
  this._activeDescendant = AdfFocusUtils.setFirstActiveDescendant(menuElement, context);
};
AdfDhtmlMenuPeer.prototype.ReplaceDomElement = function(newElement, oldElement) {
  if (this._getLazyState() != "fetching") {
    AdfDhtmlMenuPeer.superclass.ReplaceDomElement.call(this, newElement, oldElement);
    return;
  }
  var menuContent = AdfDomUtils.getFirstChildElement(newElement);
  if (menuContent == null) {
    AdfLogger.LOGGER.warning("Unexpected element received by AdfDhtmlMenuPeer.prototype.ReplaceDomElement");
    AdfDhtmlMenuPeer.superclass.ReplaceDomElement.call(this, newElement, oldElement);
    return;
  }
  var rootElement = this.getDomElement();
  rootElement.appendChild(menuContent);
  var agent = AdfAgent.AGENT;
  agent.elementsAdded(menuContent);
  this._setLazyState("contentLoaded");
  this._hideFetchingDataPopup();
  this.show(this._lazyFetchPopupHints, this._lazyFetchFocusOnFirstElement);
};
AdfDhtmlMenuPeer.prototype.PopupClosed = function(component, contentDom, popupId) {
  var rootElement = this.getDomElement();
  AdfMenuUtils.dismiss(rootElement, true, false);
  contentDom.style.display = "none";
  AdfDhtmlMenuPeer.superclass.PopupClosed.call(this, component, contentDom);
  rootElement.appendChild(contentDom);
  if (this.isContextMenu()) {
    var parent = component.getParent();
    AdfDhtmlPopupPeer.__handlePopupCanceled(parent, contentDom);
    parent.getPeer().PopupClosed(parent, null);
  }
};
AdfDhtmlMenuPeer.prototype.HandleComponentMouseOut = function(componentEvent) {
  AdfMenuUtils.unhighlightRootMenuItem();
  if (this._isSubMenu() && !this._isMenuVisible()) {
    if (AdfDhtmlMenuPeer._popupPeerWaitingForShow == this) {
      AdfDhtmlMenuPeer.cancelShowing();
    }
    var rootElement = this.getDomElement();
    AdfDomUtils.removeCSSClassName(rootElement, AdfMenuUtils.HIGHLIGHTED_STYLE_CLASS);
    AdfDomUtils.removeCSSClassName(rootElement, AdfMenuUtils.DEPRESSED_STYLE_CLASS);
  }
};
AdfDhtmlMenuPeer.prototype.HandleComponentKeyUp = function(componentEvent) {
  if (componentEvent.isCanceled() || this._isDisabled()) {
    return;
  }
  var rootElement = this.getDomElement();
  var keyCode = componentEvent.getKeyCode();
  var isSubMenu = this._isSubMenu();
  var component = this.getComponent();
  var eventSource = componentEvent.getSource();
  switch(keyCode) {
    case AdfKeyStroke.HOME_KEY:
      if (eventSource != component) {
        var firstChild = AdfFocusUtils.getFirstFocusableDescendant(this._getMenuElement());
        this._updateActiveDescendant(firstChild);
        AdfFocusUtils.focusElement(firstChild);
        componentEvent.cancel();
      }
      return;
    case AdfKeyStroke.END_KEY:
      if (eventSource != component) {
        var lastChild = AdfFocusUtils.getLastFocusableDescendant(this._getMenuElement());
        this._updateActiveDescendant(lastChild);
        AdfFocusUtils.focusElement(lastChild);
        componentEvent.cancel();
      }
      return;
    case AdfKeyStroke.ENTER_KEY:
      if (this._enterKeyDown) {
        AdfDomUtils.addCSSClassName(rootElement, AdfMenuUtils.DEPRESSED_STYLE_CLASS);
        this.show(null, true);
      }
      this._enterKeyDown = false;
      componentEvent.cancel();
      return;
    case AdfKeyStroke.SPACE_KEY:
      if (this._spaceKeyDown) {
        AdfDomUtils.addCSSClassName(rootElement, AdfMenuUtils.DEPRESSED_STYLE_CLASS);
        this.show(null, true);
      }
      this._spaceKeyDown = false;
      componentEvent.cancel();
      return;
    case AdfKeyStroke.ESC_KEY:
      if (this.isDetached()) {
        this._closeDetachedMenu();
        componentEvent.cancel();
      } else {
        if (isSubMenu) {
          if (rootElement != AdfPage.PAGE.getActiveDomElement()) {
            this.focus(component);
            this.close(true, true);
            componentEvent.cancel();
          }
        } else {
          if (this.isContextMenu()) {
            AdfMenuUtils.closeAllMenus();
            rootElement.blur();
            this.focus(component);
            var parent = component.getParent();
            parent.getPeer().hide(parent);
            componentEvent.cancel();
          } else {
            AdfLogger.LOGGER.finest("menuBar auto open mode, set to OFF due to escape pressed while on a root menu");
            AdfMenuUtils.setMenuBarAutoOpenMode(false);
            AdfMenuUtils.closeAllMenus(true);
          }
        }
      }
      return;
    default:
      break;
  }
  var openMenu = this._isMenuVisible();
  var rootMenu = this.isRootMenu();
  var isEventSource = componentEvent.getSource() == component;
  if (openMenu && rootMenu || !isEventSource) {
    var containerElement = this._scrollContentElement || this._getMenuElement();
    AdfDhtmlMenuPeer._handleMenuItemAccessKeys(containerElement, componentEvent);
  }
};
AdfDhtmlMenuPeer.prototype.HandleComponentKeyDown = function(componentEvent) {
  if (componentEvent.isCanceled() || this._isDisabled()) {
    return;
  }
  var keyCode = componentEvent.getKeyCode();
  var agent = AdfAgent.AGENT;
  if (keyCode == AdfKeyStroke.ENTER_KEY) {
    this._enterKeyDown = true;
    componentEvent.cancel();
    componentEvent.stopBubbling();
    return;
  } else {
    if (keyCode == AdfKeyStroke.SPACE_KEY) {
      this._spaceKeyDown = true;
      componentEvent.cancel();
      componentEvent.stopBubbling();
      return;
    }
  }
  if (agent.getPreferredKeyEventForRepetition() == AdfUIInputEvent.KEY_DOWN_EVENT_TYPE) {
    this._handleArrowKeys(keyCode, componentEvent);
  }
};
AdfDhtmlMenuPeer.prototype.HandleComponentKeyPress = function(componentEvent) {
  if (!componentEvent.isCanceled() && !this._isDisabled() && AdfAgent.AGENT.getPreferredKeyEventForRepetition() == AdfUIInputEvent.KEY_PRESS_EVENT_TYPE) {
    var keyCode = componentEvent.getKeyCode();
    this._handleArrowKeys(keyCode, componentEvent);
  }
};
AdfDhtmlMenuPeer.prototype.HandleComponentFocus = function(componentEvent) {
  var eventSource = componentEvent.getSource();
  var menuComponent = this.getComponent();
  if (eventSource == menuComponent) {
    var rootElement = this.getDomElement();
    if (this._isSubMenu()) {
      AdfDomUtils.addCSSClassName(rootElement, AdfMenuUtils.HIGHLIGHTED_STYLE_CLASS);
    } else {
      if (AdfMenuUtils.isMenuBarAutoOpenMode()) {
        AdfMenuUtils.dismiss(rootElement, true);
        AdfDomUtils.addCSSClassName(rootElement, AdfMenuUtils.DEPRESSED_STYLE_CLASS);
        this.show(null, false);
      } else {
        AdfMenuUtils.highlightRootMenuItem(rootElement);
      }
    }
  } else {
    var eventParentComponent = eventSource.getParent();
    if (eventParentComponent == menuComponent) {
      var clientId = eventSource.getClientId();
      var compElement = AdfAgent.AGENT.getElementById(clientId);
      var focusableElement = AdfFocusUtils.getFirstFocusableDescendant(compElement);
      if (focusableElement && focusableElement != this._activeDescendant) {
        this._updateActiveDescendant(focusableElement);
      }
    }
  }
  componentEvent.cancel();
};
AdfDhtmlMenuPeer.prototype.HandleComponentMouseOver = function(componentEvent) {
  this._cancelHiding();
  if (this._isDisabled()) {
    if (AdfMenuUtils.isMenuBarAutoOpenMode() && this.isRootMenu()) {
      AdfMenuUtils.closeAllMenus(false);
    }
    return;
  }
  if (componentEvent.isCanceled()) {
    return;
  }
  var agent = AdfAgent.AGENT;
  var nativeEvent = componentEvent.getNativeEvent();
  var rootElement = this.getDomElement();
  if (!agent.isEventInElement(nativeEvent, rootElement)) {
    return;
  }
  componentEvent.cancel();
  if (this.isContextMenu()) {
    return;
  }
  var component = this.getComponent();
  if (this._isSubMenu()) {
    AdfDomUtils.addCSSClassName(rootElement, AdfMenuUtils.HIGHLIGHTED_STYLE_CLASS);
    AdfMenuUtils.dismiss(rootElement, false);
    this._delayShow();
    if (!AdfFocusUtils.containsFocus(rootElement)) {
      this.focus(component);
    }
  } else {
    if (!this._isMenuVisible() && !AdfMenuUtils.isMenuBarAutoOpenMode()) {
      AdfMenuUtils.highlightRootMenuItem(rootElement);
    } else {
      if (AdfMenuUtils.isMenuBarAutoOpenMode()) {
        AdfMenuUtils.dismiss(rootElement, true);
        AdfDomUtils.addCSSClassName(rootElement, AdfMenuUtils.DEPRESSED_STYLE_CLASS);
        this.show(null, false);
      }
      if (!AdfFocusUtils.containsFocus(rootElement)) {
        this.focus(component);
      }
    }
  }
};
AdfDhtmlMenuPeer.prototype.HandleComponentMouseDown = function(componentEvent) {
  var component = this.getComponent();
  if (this._isDisabled() || !componentEvent.isLeftButtonPressed() || component != componentEvent.getSource()) {
    return;
  }
  var agent = AdfAgent.AGENT;
  var domEvent = componentEvent.getNativeEvent();
  var rootElement = this.getDomElement();
  var isScrollUpElement = this._scrollUpElement && agent.isEventInElement(domEvent, this._scrollUpElement);
  var isScrollDownElement = this._scrollDownElement && agent.isEventInElement(domEvent, this._scrollDownElement);
  if (isScrollUpElement || isScrollDownElement) {
    if (agent.getPlatform() == AdfAgent.IE_PLATFORM) {
      var scrollButtonDIV = isScrollUpElement ? this._scrollUpElement : this._scrollDownElement;
      if (scrollButtonDIV != AdfPage.PAGE.getActiveDomElement()) {
        scrollButtonDIV.tabIndex = 0;
        scrollButtonDIV.focus();
        scrollButtonDIV.tabIndex = -1;
      }
    }
    if (agent.getCapabilities()[AdfAgent.CAP_TOUCH_SCREEN] != AdfAgent.CAP_TOUCH_SCREEN_NONE) {
      this._startScroll(isScrollDownElement, true);
    } else {
      this._startScroll(isScrollDownElement);
    }
  } else {
    if (agent.isEventInElement(domEvent, rootElement)) {
      agent.eatEvent(domEvent);
      if (this.isContextMenu()) {
        AdfDomUtils.addCSSClassName(rootElement, AdfMenuUtils.DEPRESSED_STYLE_CLASS);
        return;
      }
      var domWindow = AdfPage.PAGE.getDomWindow();
      var isMobile = Boolean(domWindow.AdfSafariMobileAgent && AdfAgent.AGENT instanceof AdfSafariMobileAgent);
      if (this._isSubMenu()) {
        AdfDomUtils.addCSSClassName(rootElement, AdfMenuUtils.DEPRESSED_STYLE_CLASS);
        this.show(null, isMobile);
      } else {
        if (this._isMenuVisible()) {
          AdfDomUtils.addCSSClassName(rootElement, AdfMenuUtils.DEPRESSED_STYLE_CLASS);
          this.close(true, true);
          AdfLogger.LOGGER.finest("menuBar auto open mode, set to OFF due to menu clicked while menu IS visible");
          AdfMenuUtils.setMenuBarAutoOpenMode(false);
        }
      }
    }
  }
};
AdfDhtmlMenuPeer.prototype.HandleComponentMouseUp = function(componentEvent) {
  if (this._isDisabled() || !componentEvent.isLeftButtonPressed()) {
    return;
  }
  var agent = AdfAgent.AGENT;
  var domEvent = componentEvent.getNativeEvent();
  if (this._handleElement) {
    AdfDomUtils.removeCSSClassName(this._handleElement, AdfMenuUtils.DEPRESSED_STYLE_CLASS);
  }
  var isScrollUpElement = this._scrollUpElement && agent.isEventInElement(domEvent, this._scrollUpElement);
  var isScrollDownElement = this._scrollDownElement && agent.isEventInElement(domEvent, this._scrollDownElement);
  var component = this.getComponent();
  if (isScrollUpElement || isScrollDownElement) {
    this._endScroll();
    this.updateScrollIconsState();
  } else {
    if (component == componentEvent.getSource()) {
      var rootElement = this.getDomElement();
      if (agent.isEventInElement(domEvent, rootElement) && !(this.isContextMenu() || this._isSubMenu() || this._isMenuVisible())) {
        var domWindow = AdfPage.PAGE.getDomWindow();
        var isMobile = Boolean(domWindow.AdfSafariMobileAgent && AdfAgent.AGENT instanceof AdfSafariMobileAgent);
        this.show(null, isMobile);
        AdfLogger.LOGGER.finest("menuBar auto open mode, set to ON due to menu clicked while menu IS NOT visible");
        AdfMenuUtils.setMenuBarAutoOpenMode(true);
      }
    }
  }
};
AdfDhtmlMenuPeer.prototype.HandleComponentBlur = function(componentEvent) {
  var rootElement = this.getDomElement();
  var notASubMenu = !this._isSubMenu();
  var menuNotOpen = this._isSubMenu() && !this._isMenuVisible();
  var menuOpenAndDetached = this._isSubMenu() && this._isMenuVisible() && this.isDetached();
  if (notASubMenu || menuNotOpen || menuOpenAndDetached) {
    AdfDomUtils.removeCSSClassName(rootElement, AdfMenuUtils.HIGHLIGHTED_STYLE_CLASS);
  }
  if (this.isDetached() || !this._isMenuVisible()) {
    AdfDomUtils.removeCSSClassName(rootElement, AdfMenuUtils.DEPRESSED_STYLE_CLASS);
  }
};
AdfDhtmlMenuPeer.prototype.ComponentRemoved = function(component) {
  var clientId = component.getClientId();
  if (AdfMenuUtils.isMenuOpen(clientId)) {
    this.hidePopup();
  } else {
    if (this.isDetached()) {
      this._closeDetachedMenu();
    }
  }
  if (this._isDetachable()) {
    var agent = AdfAgent.AGENT;
    var closeDetachedMenuCallback = this._closeDetachedMenuCallback;
    if (closeDetachedMenuCallback) {
      agent.removeBubbleEventListener(this._closeElement, "click", closeDetachedMenuCallback);
    }
    delete this._closeElement;
    delete this._closeDetachedMenuCallback;
    var stopCallback = this._stopCallback;
    if (stopCallback) {
      agent.removeBubbleEventListener(this._handleElement, "mousedown", stopCallback);
    }
    delete this._handleElement;
    delete this._stopCallback;
  }
  if (!this._isSubMenu()) {
    AdfDhtmlMenuPeer._removeBarMenu(clientId);
  }
  if (this._areScrollButtonsDisplayed) {
    this._scrollBoxElement.removeEventListener("wheel", this._mouseWheelHandle);
    this._swipeMgr.release();
    this._swipeMgr = null;
  }
  delete this._menuElement;
  delete this._scrollUpElement;
  delete this._scrollDownElement;
  delete this._scrollUpBackgroundElement;
  delete this._scrollDownBackgroundElement;
  delete this._scrollBoxElement;
  delete this._scrollContentElement;
  AdfDhtmlMenuPeer.superclass.ComponentRemoved.call(this, component);
};
AdfDhtmlMenuPeer.prototype.ComponentDisabledChanged = function(component, domElement, newValue, oldValue) {
  AdfMenuUtils.menuItemDisabledChanged(component, domElement, newValue, this._getMenuElement());
};
AdfDhtmlMenuPeer.prototype.ComponentVisibleChanged = function(component, domElement, newValue, oldValue) {
  AdfDhtmlMenuPeer.superclass.ComponentVisibleChanged.call(this, component, domElement, newValue, oldValue);
  AdfMenuUtils.menuItemVisibleChanged(component, domElement, newValue, this._getMenuElement());
};
AdfDhtmlMenuPeer.prototype.ComponentTextChanged = function(component, domElement, newValue, oldValue) {
  if (oldValue != null) {
    var textElement = AdfDomUtils.getFirstDescendentElement(domElement, "A");
    if (textElement) {
      return AdfDomUtils.handleTextChangeWithAccessKey(component, textElement, newValue);
    }
  }
  return false;
};
AdfDhtmlMenuPeer.prototype.GetInlineEditor = function(event) {
  return AdfDhtmlSimpleTextEditor.getAnchorInlineEditor();
};
AdfDhtmlMenuPeer.prototype.setVisibleItems = function(items) {
  this._maxDisplayItems = items;
};
AdfDhtmlMenuPeer.prototype.__preferredSizeChangeNotify = function(component) {
  this.bind(component);
  if (!this.isRootMenu()) {
    return;
  }
  var parent = this.getComponentParent(component);
  var parentPeer = parent != null ? parent.getPeer() : null;
  if (parentPeer && parentPeer.__preferredSizeChangeNotify) {
    parentPeer.__preferredSizeChangeNotify(parent);
  }
};
AdfDhtmlMenuPeer._redetachMenu = function() {
  var reattachedMenuId = AdfDhtmlMenuPeer._reattachedMenuId;
  if (reattachedMenuId == null) {
    return;
  }
  var component = AdfPage.PAGE.findComponent(reattachedMenuId);
  if (component) {
    var peer = component.getPeer();
    if (peer && peer instanceof AdfDhtmlMenuPeer && peer._detachableWindow) {
      var floatingElement = peer._detachableWindow.getElement();
      floatingElement.style.left = peer._detachedMenuLeft;
      floatingElement.style.top = peer._detachedMenuTop;
      var pos = {"y":peer._detachedMenuTop, "x":peer._detachedMenuLeft};
      var menuPopup = peer._getMenuPopup();
      if (menuPopup) {
        menuPopup.setAlignPosition(pos);
      }
      peer._makeDetached();
    }
  }
  AdfDhtmlMenuPeer._reattachedMenuId = null;
};
AdfDhtmlMenuPeer._focusNextDetachedMenuKeyHandler = function() {
  if (AdfCollections.isEmpty(AdfDhtmlMenuPeer._sDetachedMenus)) {
    return;
  }
  var nextClientId;
  var lastClientId = AdfDhtmlMenuPeer._lastSelectedDetachableMenuId;
  if (lastClientId == null) {
    nextClientId = AdfDhtmlMenuPeer._sDetachedMenus[0];
  } else {
    var numDetachedMenus = AdfDhtmlMenuPeer._sDetachedMenus.length;
    if (numDetachedMenus == 1) {
      nextClientId = AdfDhtmlMenuPeer._sDetachedMenus[0];
    } else {
      var index = AdfCollections.indexOf(AdfDhtmlMenuPeer._sDetachedMenus, lastClientId);
      nextClientId = index >= numDetachedMenus - 1 ? AdfDhtmlMenuPeer._sDetachedMenus[0] : AdfDhtmlMenuPeer._sDetachedMenus[index + 1];
    }
  }
  var nextMenu = AdfPage.PAGE.findComponent(nextClientId);
  if (nextMenu) {
    var nextPeer = nextMenu.getPeer();
    nextPeer.bind(nextMenu);
    if (nextPeer._activeDescendant == null || !AdfFocusUtils.isFocusableDescendant(nextPeer._activeDescendant)) {
      nextPeer.resetActiveDescendant();
    }
    AdfFocusUtils.focusElement(nextPeer._activeDescendant);
    AdfDhtmlMenuPeer._lastSelectedDetachableMenuId = nextClientId;
  } else {
    AdfDhtmlMenuPeer._removeFromDetachedMenus(nextClientId);
    AdfDhtmlMenuPeer._focusNextDetachedMenuKeyHandler();
  }
};
AdfDhtmlMenuPeer._addToDetachedMenus = function(clientId) {
  var agent = AdfAgent.AGENT;
  if (AdfCollections.isEmpty(AdfDhtmlMenuPeer._sDetachedMenus)) {
    var isGecko = agent.getPlatform() == AdfAgent.GECKO_PLATFORM;
    if (isGecko) {
      var doc = AdfPage.PAGE.getDomDocument();
      agent.addBubbleEventListener(doc, "keypress", AdfDhtmlMenuPeer._cancelKeyPress);
    }
    AdfPage.PAGE.registerKeyStroke(AdfDhtmlMenuPeer._focusDetachedMenuKeyStroke, AdfDhtmlMenuPeer._focusNextDetachedMenuKeyHandler);
  }
  var index = AdfCollections.indexOf(AdfDhtmlMenuPeer._sDetachedMenus, clientId);
  if (index < 0) {
    AdfDhtmlMenuPeer._lastSelectedDetachableMenuId = clientId;
    AdfDhtmlMenuPeer._sDetachedMenus.push(clientId);
  }
};
AdfDhtmlMenuPeer._removeFromDetachedMenus = function(clientId) {
  AdfCollections.removeArrayValue(AdfDhtmlMenuPeer._sDetachedMenus, clientId);
  var allDetachableMenusClosed = AdfCollections.isEmpty(AdfDhtmlMenuPeer._sDetachedMenus);
  if (allDetachableMenusClosed || clientId == AdfDhtmlMenuPeer._lastSelectedDetachableMenuId) {
    AdfDhtmlMenuPeer._lastSelectedDetachableMenuId = null;
  }
  if (allDetachableMenusClosed) {
    AdfPage.PAGE.unregisterKeyStroke(AdfDhtmlMenuPeer._focusDetachedMenuKeyStroke);
    var agent = AdfAgent.AGENT;
    var isGecko = agent.getPlatform() == AdfAgent.GECKO_PLATFORM;
    if (isGecko) {
      var doc = AdfPage.PAGE.getDomDocument();
      agent.removeBubbleEventListener(doc, "keypress", AdfDhtmlMenuPeer._cancelKeyPress);
    }
  }
};
AdfDhtmlMenuPeer._cancelKeyPress = function(event) {
  var keyCode = AdfAgent.AGENT.getKeyCode(event);
  if (event.ctrlKey && event.shiftKey && keyCode == AdfKeyStroke.W_KEY) {
    AdfAgent.AGENT.eatEvent(event);
  }
};
AdfDhtmlMenuPeer._menuBarKeyHandler = function(event) {
  AdfDhtmlMenuPeer._focusMenuBar();
};
AdfDhtmlMenuPeer._addBarMenu = function(clientId) {
  var barMenus = AdfDhtmlMenuPeer._sBarMenus;
  if (barMenus.length == 0) {
    AdfPage.PAGE.registerKeyStroke(AdfDhtmlMenuPeer._menuBarKeyStroke, AdfDhtmlMenuPeer._menuBarKeyHandler);
  }
  barMenus.push(clientId);
};
AdfDhtmlMenuPeer._removeBarMenu = function(clientId) {
  var barMenus = AdfDhtmlMenuPeer._sBarMenus;
  AdfCollections.removeArrayValue(barMenus, clientId);
  if (barMenus.length == 0) {
    AdfPage.PAGE.unregisterKeyStroke(AdfDhtmlMenuPeer._menuBarKeyStroke);
  }
};
AdfDhtmlMenuPeer._focusMenuBar = function() {
  var barMenus = AdfDhtmlMenuPeer._sBarMenus;
  AdfAssert.assert(barMenus.length > 1);
  var clientId = barMenus[0];
  var component = AdfPage.PAGE.findComponent(clientId);
  var parent = component.getParent();
  AdfAssert.assert(!(parent instanceof AdfRichMenu));
  var peer = component.getPeer();
  var parentMenuBarId = peer._getParentId();
  var barElement = AdfAgent.AGENT.getElementById(parentMenuBarId);
  AdfFocusUtils.focusFirstTabStop(barElement);
};
AdfDhtmlMenuPeer._handleMenuItemAccessKeys = function(containerElement, componentEvent) {
  var keyStroke = componentEvent.getKeyStroke();
  var modifiers = keyStroke.getModifiers();
  if (modifiers & AdfKeyStroke.CTRL_MASK || modifiers & AdfKeyStroke.ALT_MASK || modifiers & AdfKeyStroke.META_MASK) {
    return;
  }
  if (modifiers & AdfKeyStroke.SHIFT_MASK) {
    modifiers = modifiers >> AdfKeyStroke.SHIFT_MASK;
    keyStroke = AdfKeyStroke.getKeyStroke(keyStroke.getKeyCode(), modifiers);
  }
  var keyPressed = keyStroke.toMarshalledString().toUpperCase();
  var menuItemElements = containerElement.getElementsByTagName("tr");
  var numItems = menuItemElements.length;
  for (var i = 0;i < numItems;i++) {
    var menuItem = menuItemElements[i];
    if (menuItem && menuItem.nodeType == 1) {
      var id = menuItem.id;
      var menuItemAccessKey = menuItem.getAttribute("accessKey");
      if (menuItemAccessKey) {
        if (keyPressed == menuItemAccessKey.toUpperCase()) {
          AdfFocusUtils.focusElement(menuItem);
          componentEvent.cancel();
          return;
        }
      }
    }
  }
};
AdfDhtmlMenuPeer.prototype._handleArrowKeys = function(keyCode, componentEvent) {
  var evt = componentEvent.getNativeEvent();
  if (evt.ctrlKey) {
    this._handleCtrlArrowKeys(keyCode, componentEvent);
    return;
  }
  if (evt.altKey || evt.shiftKey || evt.metaKey) {
    return;
  }
  var component = componentEvent.getSource();
  if (component == this.getComponent()) {
    return;
  }
  var rootElement = componentEvent.getSource().getPeer().getDomElement();
  switch(keyCode) {
    case AdfKeyStroke.ARROWUP_KEY:
      this._focusPreviousMenuItem(rootElement);
      componentEvent.cancel();
      break;
    case AdfKeyStroke.ARROWDOWN_KEY:
      this._focusNextMenuItem(rootElement);
      componentEvent.cancel();
      break;
    case AdfKeyStroke.ARROWLEFT_KEY:
      this._handleMenuItemLeftArrowKey(componentEvent);
      break;
    case AdfKeyStroke.ARROWRIGHT_KEY:
      this._handleMenuItemRightArrowKey(componentEvent);
      break;
  }
};
AdfDhtmlMenuPeer.prototype._handleCtrlArrowKeys = function(keyCode, componentEvent) {
  if (this.isDetached() || this._detachableWindow && this._isMenuVisible()) {
    var isIE = AdfAgent.AGENT.getPlatform() == AdfAgent.IE_PLATFORM;
    var isEqualsKey = isIE ? keyCode == 187 : keyCode == 61;
    var evt = componentEvent.getNativeEvent();
    if (evt.altKey && isEqualsKey) {
      this._moveDetachable(0, 0);
      componentEvent.cancel();
    } else {
      var cancelEvent = true;
      switch(keyCode) {
        case AdfKeyStroke.ARROWUP_KEY:
          this._moveDetachable(0, -20);
          break;
        case AdfKeyStroke.ARROWDOWN_KEY:
          this._moveDetachable(0, 20);
          break;
        case AdfKeyStroke.ARROWLEFT_KEY:
          this._moveDetachable(-20, 0);
          break;
        case AdfKeyStroke.ARROWRIGHT_KEY:
          this._moveDetachable(20, 0);
          break;
        default:
          cancelEvent = false;
      }
      if (cancelEvent) {
        componentEvent.cancel();
      }
    }
  }
};
AdfDhtmlMenuPeer.prototype._handleMenuItemLeftArrowKey = function(componentEvent) {
  var component = this.getComponent();
  if (this.isRootMenu()) {
    this.focus(component);
    this.close(true, true);
    AdfMenuUtils.MenuBarAutoOpenMode = false;
  } else {
    if (!this.isDetached() && !this.isContextMenu()) {
      this.focus(component);
      this.close(true, true);
    }
  }
  componentEvent.cancel();
};
AdfDhtmlMenuPeer.prototype._handleMenuItemRightArrowKey = function(componentEvent) {
  var eventComponent = componentEvent.getSource();
  if (eventComponent instanceof AdfRichMenu) {
    var menuPeer = eventComponent.getPeer();
    menuPeer.show(null, true);
    componentEvent.cancel();
    return;
  }
  if (this.isDetached() || this.isContextMenu()) {
    componentEvent.cancel();
    return;
  }
  if (this.isRootMenu()) {
    var component = this.getComponent();
    this.focus(component);
    this.close(true, true);
    AdfLogger.LOGGER.finest("menuBar auto open mode, set to OFF due to right arrow key pressed on root menu item");
    AdfMenuUtils.setMenuBarAutoOpenMode(false);
    componentEvent.cancel();
    return;
  }
};
AdfDhtmlMenuPeer.prototype._focusNextMenuItem = function(rootElement) {
  AdfAssert.assertDomElement(this._activeDescendant);
  AdfAssert.assert(rootElement == this._activeDescendant);
  if (!this._activeDescendant) {
    AdfLogger.LOGGER.warning("Menu has lost its assigned activeDescendant!");
    this.resetActiveDescendant();
  }
  var nextItem = AdfFocusUtils.focusNextActiveDescendant(this._getMenuElement(), rootElement, true);
  AdfAssert.assertDomElement(nextItem);
  this._activeDescendant = nextItem;
  this.updateScrollIconsState();
};
AdfDhtmlMenuPeer.prototype._focusPreviousMenuItem = function(rootElement) {
  AdfAssert.assertDomElement(this._activeDescendant);
  AdfAssert.assert(rootElement == this._activeDescendant);
  if (!this._activeDescendant) {
    AdfLogger.LOGGER.warning("Menu has lost its assigned activeDescendant!");
    this.resetActiveDescendant();
  }
  var previousItem = AdfFocusUtils.focusPreviousActiveDescendant(this._getMenuElement(), rootElement, true);
  AdfAssert.assertDomElement(previousItem);
  this._activeDescendant = previousItem;
  this.updateScrollIconsState();
};
AdfDhtmlMenuPeer.prototype._onHandleClick = function(event) {
  AdfAgent.AGENT.eatEvent(event);
  AdfDomUtils.addCSSClassName(this._handleElement, AdfMenuUtils.DEPRESSED_STYLE_CLASS);
};
AdfDhtmlMenuPeer.prototype._initElements = function(component, clientId, menuElement) {
  var agent = AdfAgent.AGENT;
  if (this._isDetachable()) {
    var closeSubId = AdfRichUIPeer.CreateSubId(clientId, "close");
    this._closeElement = agent.getElementById(closeSubId);
    this._closeDetachedMenuCallback = this.createCallback(this._closeDetachedMenu);
    agent.addBubbleEventListener(this._closeElement, "click", this._closeDetachedMenuCallback);
    var handleSubId = AdfRichUIPeer.CreateSubId(clientId, "handle");
    this._handleElement = agent.getElementById(handleSubId);
    this._stopCallback = this.createCallback(this._onHandleClick);
    agent.addBubbleEventListener(this._handleElement, "mousedown", this._stopCallback);
  }
  var scrollContentSubId = AdfRichUIPeer.CreateSubId(clientId, "ScrollContent");
  this._scrollContentElement = agent.getElementById(scrollContentSubId);
  var menuItems = this._scrollContentElement.rows;
  if (menuItems.length < this._maxDisplayItems) {
    this._areScrollButtonsDisplayed = false;
    return;
  }
  var visibleItems = new Array;
  for (i = 0;i < menuItems.length;i++) {
    var menuItem = menuItems[i];
    if (menuItem.style.display != "none") {
      visibleItems.push(menuItem);
    }
  }
  this._areScrollButtonsDisplayed = visibleItems.length > this._maxDisplayItems;
  if (this._areScrollButtonsDisplayed) {
    var scrollUpSubId = AdfRichUIPeer.CreateSubId(clientId, "ScrollUp");
    this._scrollUpElement = agent.getElementById(scrollUpSubId);
    this._scrollUpElement.style.display = "block";
    var scrollUpBackgroundSubId = AdfRichUIPeer.CreateSubId(clientId, "sUpBg");
    this._scrollUpBackgroundElement = agent.getElementById(scrollUpBackgroundSubId);
    var scrollDownSubId = AdfRichUIPeer.CreateSubId(clientId, "ScrollDown");
    this._scrollDownElement = agent.getElementById(scrollDownSubId);
    this._scrollDownElement.style.display = "block";
    var scrollDownBackgroundSubId = AdfRichUIPeer.CreateSubId(clientId, "sDwnBg");
    this._scrollDownBackgroundElement = agent.getElementById(scrollDownBackgroundSubId);
    var scrollBoxSubId = AdfRichUIPeer.CreateSubId(clientId, "ScrollBox");
    this._scrollBoxElement = agent.getElementById(scrollBoxSubId);
    var firstMenuItemTop = visibleItems[0].offsetTop;
    var firstMenuItemNotInScrollBoxTop = visibleItems[this._maxDisplayItems].offsetTop - 2;
    var height = firstMenuItemNotInScrollBoxTop - firstMenuItemTop;
    this._scrollBoxElement.style.height = height + "px";
    this._mouseWheelHandle = this.createCallback(this._mouseWheel);
    this._scrollBoxElement.addEventListener("wheel", this._mouseWheelHandle);
    var callbacks = {};
    callbacks[AdfSwipeSupport.PANNING_CALLBACK] = this.createCallback(this._handlePanning);
    var options = {};
    options[AdfSwipeSupport.MODE] = AdfSwipeSupport.MODE_VERTICAL;
    this._swipeMgr = new AdfSwipeSupport(this._scrollBoxElement, callbacks, options);
  }
};
AdfDhtmlMenuPeer.prototype._createMenuPopupHints = function(baseHints, focusOnFirstElement) {
  var hints = new Object;
  var rootElement = this.getDomElement();
  var component = this.getComponent();
  hints[AdfDhtmlPopupHints.TYPE] = AdfDhtmlPopupHints.TYPE_MENU;
  hints[AdfDhtmlPopupHints.AUTODISMISS] = AdfDhtmlPopupHints.AUTODISMISS_MENU;
  hints[AdfDhtmlPopupHints.ALIGN_ELEMENT] = rootElement;
  hints[AdfDhtmlPopupHints.FOCUS] = focusOnFirstElement ? true : false;
  var menuTitle = component.getText();
  if (menuTitle == null) {
    menuTitle = component.getShortDesc();
  }
  hints[AdfDhtmlPopupHints.TITLE] = menuTitle;
  hints[AdfDhtmlPopupHints.ANIMATE] = AdfRichPopup.ANIMATE_DEFAULT;
  hints[AdfDhtmlPopupHints.CLOSE_ON_ESCAPE] = false;
  if (baseHints == null || baseHints[AdfDhtmlPopupHints.MOUSEPOSITION] == null) {
    if (this._isSubMenu() || AdfMenuUtils.isInOverflow(rootElement)) {
      hints[AdfRichPopup.HINT_ALIGN] = AdfRichPopup.ALIGN_END_BEFORE;
    } else {
      hints[AdfRichPopup.HINT_ALIGN] = AdfRichPopup.ALIGN_AFTER_START;
    }
  }
  AdfCollections.copyInto(hints, baseHints);
  return hints;
};
AdfDhtmlMenuPeer.prototype._showFetchingDataPopup = function() {
  var agent = AdfAgent.AGENT;
  var component = this.getComponent();
  var rootElement = this.getDomElement();
  var id = rootElement.getAttribute("id");
  var fetchingMsgId = AdfRichUIPeer.CreateSubId(id, "lazy-fetch-message");
  var fetchingMsgContainer = agent.getElementById(fetchingMsgId);
  var fetchingMsgElement = AdfDomUtils.getFirstChildElement(fetchingMsgContainer);
  var hints = this._createMenuPopupHints(null, false);
  hints[AdfDhtmlPopupHints.TYPE] = AdfDhtmlPopupHints.TYPE_INLINESELECTOR;
  AdfDomUtils.setVisible(fetchingMsgElement, true);
  AdfDhtmlMenuPeer.superclass.showPopup.call(this, component, fetchingMsgElement, hints, fetchingMsgId);
};
AdfDhtmlMenuPeer.prototype._hideFetchingDataPopup = function() {
  var component = this.getComponent();
  var rootElement = this.getDomElement();
  var id = rootElement.getAttribute("id");
  var fetchingMsgId = AdfRichUIPeer.CreateSubId(id, "lazy-fetch-message");
  AdfDhtmlMenuPeer.superclass.hidePopup.call(this, component, fetchingMsgId);
};
AdfDhtmlMenuPeer.prototype._reattachMenu = function() {
  if (!this.isDetached()) {
    return;
  }
  var component = this.getComponent();
  var clientId = component.getClientId();
  AdfDhtmlMenuPeer._reattachedMenuId = clientId;
  AdfMenuUtils.addOpenMenu(clientId);
  AdfDhtmlMenuPeer._removeFromDetachedMenus(clientId);
  this._showShadow(false);
  var reattachXY = this._calculateReattachPosition();
  this._isDetached = false;
  if (AdfPage.PAGE.isAnimationEnabled()) {
    var reattachLeftTop = {"left":reattachXY["x"], "top":reattachXY["y"]};
    this._animateReattach(reattachLeftTop);
  } else {
    this._moveShadow(true);
    var menuPopup = this._getMenuPopup();
    if (menuPopup) {
      menuPopup.setAlignPosition(reattachXY);
    }
    AdfDomUtils.removeCSSClassName(this._getMenuElement(), AdfMenuUtils.DETACHED_STYLE_CLASS);
  }
};
AdfDhtmlMenuPeer.prototype._animateReattach = function(reattachPosition) {
  AdfDomUtils.removeCSSClassName(this._getMenuElement(), AdfMenuUtils.DETACHED_STYLE_CLASS);
  var element = this._detachableWindow.getElement();
  var top = reattachPosition["y"];
  var left = reattachPosition["x"];
  var animDuration = 300;
  var animationObjects = [{element:element, properties:reattachPosition}];
  AdfDhtmlElementAnimator.animate(AdfDhtmlElementAnimator.FRAME_METHOD_SLOW_FAST_SLOW, animDuration, animationObjects, null, AdfDhtmlMenuPeer._animateReattachComplete, [this, top, left]);
};
AdfDhtmlMenuPeer._animateReattachComplete = function(args) {
  var peer = args[0];
  var top = args[1];
  var left = args[2];
  peer._moveShadow(true);
  var pos = {"y":top, "x":left};
  var menuPopup = peer._getMenuPopup();
  if (menuPopup) {
    menuPopup.setAlignPosition(pos);
  }
};
AdfDhtmlMenuPeer.prototype._calculateReattachPosition = function() {
  var positionManager = AdfPage.PAGE.getPositionManager();
  var rootElement = this.getDomElement();
  var menuElement = this._getMenuElement();
  var alignmentHint = AdfRichPopup.ALIGN_END_BEFORE;
  var height = menuElement.clientHeight - 4;
  var width = menuElement.clientWidth + AdfDhtmlShadowDecorator.getShadowSize();
  return positionManager.calculatePlacementPosition(height, width, alignmentHint, rootElement, null);
};
AdfDhtmlMenuPeer.prototype._contains = function(element) {
  var domElement = this.getDomElement();
  var insideElement = AdfDomUtils.isAncestorOrSelf(domElement, element);
  if (this._getLazyState() == "noContent") {
    return insideElement;
  }
  var insidePopup = AdfDomUtils.isAncestor(this._getMenuElement(), element);
  return insideElement || insidePopup;
};
AdfDhtmlMenuPeer.prototype._getParentId = function() {
  if (!this._parentId) {
    var el = this.getDomElement().parentNode;
    do {
      var id = el.getAttribute("id");
      el = el.parentNode;
    } while (!id && el);
    if (id) {
      this._parentId = id;
    }
  }
  return this._parentId;
};
AdfDhtmlMenuPeer.prototype._getDepth = function() {
  if (!this._depth) {
    var rootElement = this.getDomElement();
    this._depth = parseInt(rootElement.getAttribute(AdfMenuUtils.MENU_DEPTH_KEY));
  }
  return this._depth;
};
AdfDhtmlMenuPeer.prototype._isSubMenu = function() {
  return this._getDepth() > 1;
};
AdfDhtmlMenuPeer.prototype._isDisabled = function() {
  var rootElement = this.getDomElement();
  return rootElement.disabled || AdfDomUtils.containsCSSClassName(rootElement, AdfRichUIPeer.DISABLED_STYLECLASS);
};
AdfDhtmlMenuPeer.prototype._isDetachable = function() {
  var component = this.getComponent();
  return component.getDetachable();
};
AdfDhtmlMenuPeer.prototype._handleHideRequest = function(component, clientId) {
  AdfAssert.assert(!this.isDetached(), "this method is not intended for detached menus");
  if (this.isRootMenu()) {
    var domElement = this.getDomElement();
    AdfDomUtils.removeCSSClassName(domElement, AdfMenuUtils.DEPRESSED_STYLE_CLASS);
    AdfDomUtils.removeCSSClassName(domElement, AdfMenuUtils.HIGHLIGHTED_STYLE_CLASS);
  }
  if (AdfDhtmlMenuPeer._popupPeerWaitingForShow) {
    var peer = AdfDhtmlMenuPeer._popupPeerWaitingForShow;
    if (this._contains(peer.getDomElement())) {
      AdfDhtmlMenuPeer.cancelShowing();
    }
  }
  if (this._scrollBoxElement) {
    this._scrollBoxElement.scrollTop = 0;
  }
  AdfMenuUtils.removeOpenMenu(clientId);
};
AdfDhtmlMenuPeer.prototype._createDetachableWindow = function() {
  if (this._isMenuVisible() && this._detachableWindow == null) {
    this._detachableWindow = new AdfRepositionable(this._getMenuPopup(), this._handleElement);
    this._detachableWindow.setDragStartHandler(this.createCallback(this._dragStart));
    this._detachableWindow.setDragEndHandler(this.createCallback(this._dragEnd));
  }
};
AdfDhtmlMenuPeer.prototype._dragStart = function() {
  this._deselectElement();
  this._showShadow(false);
  var rootElement = this.getDomElement();
  AdfMenuUtils.dismiss(rootElement, true);
  var floatingElement = this._detachableWindow.getElement();
  this._detachedMenuLeft = floatingElement.style.left;
  this._detachedMenuTop = floatingElement.style.top;
  var clientId = this.getComponent().getClientId();
  AdfMenuUtils.removeOpenMenu(clientId);
  AdfDhtmlMenuPeer._addToDetachedMenus(clientId);
  AdfLogger.LOGGER.finest("menuBar auto open mode, set to OFF due to menu first becoming detached");
  AdfMenuUtils.setMenuBarAutoOpenMode(false);
};
AdfDhtmlMenuPeer.prototype._dragEnd = function() {
  var menuPopup = this._getMenuPopup();
  AdfAssert.assert(menuPopup != null, "menuPopup should not disappear during a drag.");
  if (!menuPopup) {
    return;
  }
  menuPopup.setAlignElement(null);
  var pos = {"y":menuPopup.getTop(), "x":menuPopup.getLeft()};
  menuPopup.setAlignPosition(pos);
  this._makeDetached();
  this._moveShadow(true);
  menuPopup.activate();
  AdfMenuUtils.closeAllMenus();
};
AdfDhtmlMenuPeer.prototype._delayPopupHiding = function(deltaTimeout) {
  if (this._popupHidingHandle) {
    this._cancelHiding();
  }
  this._popupHidingHandle = AdfPage.PAGE.getDomWindow().setTimeout(this.createCallback(this._delayPopupHidingCallback), AdfDhtmlMenuPeer._OPEN_CLOSE_DELAY - deltaTimeout);
};
AdfDhtmlMenuPeer.prototype._delayPopupHidingCallback = function() {
  var component = this.getComponent();
  if (component && this.isPopupVisible(component, component.getClientId())) {
    this.hidePopup();
  }
};
AdfDhtmlMenuPeer.prototype._delayShow = function() {
  AdfDhtmlMenuPeer.cancelShowing();
  AdfDhtmlMenuPeer._popupShowingHandle = AdfPage.PAGE.getDomWindow().setTimeout(this.createCallback(this._delayShowCallback), AdfDhtmlMenuPeer._OPEN_CLOSE_DELAY);
  AdfDhtmlMenuPeer._popupPeerWaitingForShow = this;
};
AdfDhtmlMenuPeer.prototype._delayShowCallback = function() {
  var component = this.getComponent();
  if (!this.isPopupVisible(component, component.getClientId())) {
    delete AdfDhtmlMenuPeer._popupPeerWaitingForShow;
    delete AdfDhtmlMenuPeer._popupShowingHandle;
    this.show(null, false);
  } else {
    this._reattachMenu();
  }
};
AdfDhtmlMenuPeer.prototype._cancelHiding = function() {
  if (this._popupHidingHandle) {
    window.clearTimeout(this._popupHidingHandle);
    delete this._popupHidingHandle;
    var waitingForShow = AdfDhtmlMenuPeer._popupPeerWaitingForShow;
    if (waitingForShow) {
      if (waitingForShow._getDepth() <= this._getDepth()) {
        AdfDhtmlMenuPeer.cancelShowing();
      }
    }
  }
};
AdfDhtmlMenuPeer.prototype.__makeDetached = function() {
  this._makeDetached();
};
AdfDhtmlMenuPeer.prototype._makeDetached = function() {
  AdfDomUtils.removeCSSClassName(this._handleElement, AdfMenuUtils.DEPRESSED_STYLE_CLASS);
  var floatingElement = this._detachableWindow.getElement();
  this._isDetached = true;
  this._detachedMenuLeft = floatingElement.style.left;
  this._detachedMenuTop = floatingElement.style.top;
  AdfDomUtils.addCSSClassName(this._getMenuElement(), AdfMenuUtils.DETACHED_STYLE_CLASS);
  AdfMenuUtils.dismiss(this.getDomElement().parentNode, true, true);
  this._getMenuPopup().autoSize();
};
AdfDhtmlMenuPeer.prototype._deselectElement = function() {
  var rootElement = this.getDomElement();
  AdfDomUtils.removeCSSClassName(rootElement, AdfMenuUtils.HIGHLIGHTED_STYLE_CLASS);
  AdfDomUtils.removeCSSClassName(rootElement, AdfMenuUtils.DEPRESSED_STYLE_CLASS);
};
AdfDhtmlMenuPeer.prototype._closeDetachedMenu = function(event) {
  var component = this.getComponent();
  var clientId = component.getClientId();
  AdfDomUtils.removeCSSClassName(this._getMenuElement(), AdfMenuUtils.DETACHED_STYLE_CLASS);
  this._isDetached = false;
  var rootElement = this.getDomElement();
  AdfDomUtils.removeCSSClassName(rootElement, AdfMenuUtils.HIGHLIGHTED_STYLE_CLASS);
  AdfDhtmlMenuPeer._removeFromDetachedMenus(clientId);
  if (this._detachableWindow) {
    this._detachableWindow.destroy();
  }
  delete this._detachableWindow;
  if (clientId == AdfDhtmlMenuPeer._reattachedMenuId) {
    AdfDhtmlMenuPeer._reattachedMenuId = null;
  }
  AdfDhtmlMenuPeer.superclass.hidePopup.call(this, component, clientId);
  AdfMenuUtils.closeAllMenus();
  AdfMenuUtils.restoreFocusToLastOpenedRootMenu();
};
AdfDhtmlMenuPeer.prototype._moveDetachable = function(x, y) {
  this._dragStart();
  var floatingElement = this._detachableWindow.getElement();
  floatingElement.style.left = floatingElement.offsetLeft + x + "px";
  floatingElement.style.top = floatingElement.offsetTop + y + "px";
  this._dragEnd();
};
AdfDhtmlMenuPeer.prototype._getShadowAnchor = function() {
  var menuPopup = this._getMenuPopup();
  if (menuPopup != null && menuPopup.getShadowAnchor() != null) {
    return menuPopup.getShadowAnchor();
  }
};
AdfDhtmlMenuPeer.prototype._showShadow = function(showShadow) {
  var shadowAnchor = this._getShadowAnchor();
  if (AdfDhtmlShadowDecorator.hasShadowDecorator(shadowAnchor)) {
    AdfDhtmlShadowDecorator.showShadowDecorator(shadowAnchor, showShadow);
  }
};
AdfDhtmlMenuPeer.prototype._moveShadow = function(showShadow) {
  var shadowAnchor = this._getShadowAnchor();
  if (shadowAnchor != null && AdfDhtmlShadowDecorator.hasShadowDecorator(shadowAnchor)) {
    AdfDhtmlShadowDecorator.moveShadowDecorator(shadowAnchor);
    AdfDhtmlShadowDecorator.showShadowDecorator(shadowAnchor, showShadow);
  }
};
AdfDhtmlMenuPeer.prototype.__startScroll = function(isScrollDown, isTimerSkipped) {
  this._startScroll(isScrollDown, isTimerSkipped);
};
AdfDhtmlMenuPeer.prototype._startScroll = function(isScrollDown, isTimerSkipped) {
  this._scrollDelta = AdfDhtmlMenuPeer._SCROLL_DELTA;
  if (isTimerSkipped) {
    this._scrollDelta = AdfDhtmlMenuPeer._JUMP_SCROLL_DELTA;
  }
  if (!isScrollDown) {
    this._scrollDelta *= -1;
  }
  if (isTimerSkipped) {
    this._scroll();
  } else {
    var scrollStub = this.createCallback(this._scroll);
    this._scrollTimer = setInterval(scrollStub, 10);
  }
};
AdfDhtmlMenuPeer.prototype._endScroll = function() {
  if (this._scrollTimer) {
    clearInterval(this._scrollTimer);
  }
  this._scrollTimer = null;
  var isScrollUp = this._scrollDelta < 0;
  var currentScrollSpot = this._scrollBoxElement.scrollTop;
  var menuItems = this._scrollContentElement.rows;
  var n = menuItems.length;
  if (isScrollUp) {
    for (var i = n - 1;i > -1;i--) {
      var menuItem = menuItems[i];
      if (menuItem.style.display != "none") {
        var menuItemOffsetTop = menuItem.offsetTop;
        if (currentScrollSpot >= menuItemOffsetTop) {
          this._scrollBoxElement.scrollTop = menuItemOffsetTop;
          break;
        }
      }
    }
  } else {
    var containerHeight = this._scrollBoxElement.offsetHeight;
    var scrollBottom = currentScrollSpot + containerHeight;
    for (var i = 0;i < n;i++) {
      var menuItem = menuItems[i];
      if (menuItem.style.display != "none") {
        var menuItemOffsetBottom = menuItem.offsetTop + menuItem.offsetHeight;
        if (scrollBottom <= menuItemOffsetBottom) {
          this._scrollBoxElement.scrollTop = currentScrollSpot + (menuItemOffsetBottom - scrollBottom);
          break;
        }
      }
    }
  }
};
AdfDhtmlMenuPeer.prototype._getMenuItemHeight = function() {
  if (this._menuItemHeight != null) {
    return this._menuItemHeight;
  }
  var childElement = AdfDomUtils.getFirstChildElement(this._scrollContentElement);
  var menuItem = AdfDomUtils.getFirstChildElement(childElement);
  this._menuItemHeight = menuItem.clientHeight;
  if (this._menuItemHeight == 0) {
    this._menuItemHeight = menuItem.scrollHeight;
  }
  return this._menuItemHeight;
};
AdfDhtmlMenuPeer.prototype._scroll = function() {
  this._scrollBoxElement.scrollTop += this._scrollDelta;
  var scrollOffset = this._scrollBoxElement.scrollTop;
  var maxScrollOffset = this._scrollContentElement.offsetHeight - this._scrollBoxElement.offsetHeight;
  if (scrollOffset <= 0 || scrollOffset >= maxScrollOffset) {
    this._endScroll();
  }
  this.updateScrollIconsState();
};
AdfDhtmlMenuPeer.prototype._getMenuElement = function() {
  if (this._menuElement == null) {
    var rootElement = this.getDomElement();
    var id = rootElement.getAttribute("id");
    var menuId = AdfRichUIPeer.CreateSubId(id, "menu");
    this._menuElement = AdfAgent.AGENT.getElementById(menuId);
  }
  return this._menuElement;
};
AdfDhtmlMenuPeer.prototype._getMenuPopup = function() {
  var component = this.getComponent();
  var clientId = component.getClientId();
  return this.getPopupWindow(component, clientId);
};
AdfDhtmlMenuPeer.prototype._isMenuVisible = function() {
  return this._getMenuPopup() ? true : false;
};
AdfDhtmlMenuPeer.prototype.isContentLoaded = function() {
  return this._lazyState != null && this._lazyState == "contentLoaded";
};
AdfDhtmlMenuPeer.prototype._getLazyState = function() {
  if (this._lazyState == null) {
    this._lazyState = this._getMenuElement() == null ? "noContent" : "contentLoaded";
  }
  return this._lazyState;
};
AdfDhtmlMenuPeer.prototype._setLazyState = function(newState) {
  this._lazyState = newState;
};
AdfDhtmlMenuPeer.prototype._updateActiveDescendant = function(newActiveDescendant) {
  AdfAssert.assertDomElement(newActiveDescendant);
  if (this._activeDescendant) {
    this._activeDescendant.setAttribute("tabIndex", "-1");
  }
  newActiveDescendant.setAttribute("tabIndex", "0");
  this._activeDescendant = newActiveDescendant;
};
AdfDhtmlMenuPeer.prototype.SimulateMouseOnDescendant = function(targetComponent, domElement, mouseEvent) {
  AdfDhtmlMenuPeer.superclass.SimulateMouseOnDescendant.call(this, targetComponent, domElement, mouseEvent);
  if (this.isContextMenu()) {
    return;
  }
  if (!this._isMenuVisible()) {
    this.show(null, false);
  }
};
AdfDhtmlMenuPeer.prototype._mouseWheel = function(event) {
  AdfAgent.AGENT.eatEvent(event);
  this._scrollBoxElement.scrollTop += event.deltaY;
  this.updateScrollIconsState();
};
AdfDhtmlMenuPeer.prototype._handlePanning = function(event) {
  var deltaY = event.deltaY;
  deltaY *= -1;
  this._scrollBoxElement.scrollTop += deltaY;
  this.updateScrollIconsState();
};
