UNPKG

@progress/kendo-ui

Version:

This package is part of the [Kendo UI for jQuery](http://www.telerik.com/kendo-ui) suite.

1,318 lines (1,086 loc) 116 kB
import './kendo.popup.js'; import './kendo.data.js'; import './kendo.icons.js'; import './kendo.core.js'; import './kendo.licensing.js'; import '@progress/kendo-licensing'; import './kendo.data.odata.js'; import './kendo.data.xml.js'; import './kendo.html.icon.js'; import './kendo.html.base.js'; import '@progress/kendo-svg-icons'; const __meta__ = { id: "menu", name: "Menu", category: "web", description: "The Menu widget displays hierarchical data as a multi-level menu.", depends: [ "popup", "data", "data.odata" ] }; (function($, undefined$1) { var kendo = window.kendo, ui = kendo.ui, activeElement = kendo._activeElement, touch = (kendo.support.touch && kendo.support.mobileOS), isArray = Array.isArray, HierarchicalDataSource = kendo.data.HierarchicalDataSource, MOUSEDOWN = "mousedown", CLICK = "click", DELAY = 30, SCROLLSPEED = 50, extend = $.extend, each = $.each, encode = kendo.htmlEncode, template = kendo.template, keys = kendo.keys, Widget = ui.Widget, excludedNodesRegExp = /^(ul|a|div)$/i, NS = ".kendoMenu", IMG = "img", OPEN = "open", MENU = "k-menu", LINK = "k-link k-menu-link", LINK_SELECTOR = ".k-link", ICON_SELECTOR = ".k-menu-expand-arrow", LAST = "k-last", CLOSE = "close", TIMER = "timer", FIRST = "k-first", IMAGE = "k-image", SELECT = "select", ZINDEX = "zIndex", ACTIVATE = "activate", DEACTIVATE = "deactivate", POINTERDOWN = "touchstart" + NS + " MSPointerDown" + NS + " pointerdown" + NS, pointers = kendo.support.pointers, msPointers = kendo.support.msPointers, allPointers = msPointers || pointers, CHANGE = "change", ERROR = "error", TOUCHSTART = kendo.support.touch ? "touchstart" : "", MOUSEENTER = pointers ? "pointerover" : (msPointers ? "MSPointerOver" : "mouseenter"), MOUSELEAVE = pointers ? "pointerout" : (msPointers ? "MSPointerOut" : "mouseleave"), MOUSEWHEEL = "DOMMouseScroll" + NS + " mousewheel" + NS, RESIZE = kendo.support.resize + NS, POPUP_ID_ATTR = "group", POPUP_OPENER_ATTR = "groupparent", DOCUMENT_ELEMENT = $(document.documentElement), KENDOPOPUP = "kendoPopup", HOVERSTATE = "k-hover", FOCUSEDSTATE = "k-focus", DISABLEDSTATE = "k-disabled", SELECTEDSTATE = "k-selected", menuSelector = ".k-menu", groupSelector = ".k-menu-group", animationContainerSelector = ".k-animation-container", childAnimationContainerSelector = ".k-child-animation-container", popupSelector = ".k-menu-popup ," + animationContainerSelector, allItemsSelector = ":not(.k-list) > .k-item:not([role='treeitem'])", disabledSelector = ".k-item.k-disabled", itemSelector = ".k-item", availableItemsSelector = ".k-item:not(.k-disabled)", linkSelector = ".k-item:not(.k-disabled) > .k-link", exclusionSelector = ":not(.k-item.k-separator):visible", templateSelector = "div:not(.k-animation-container,.k-list-container)", scrollButtonSelector = ".k-menu-scroll-button", touchPointerTypes = { "2": 1, "touch": 1 }, STRING = "string", DATABOUND = "dataBound", ARIA_EXPANDED = "aria-expanded", ROLE = "role", bindings = { text: "dataTextField", url: "dataUrlField", spriteCssClass: "dataSpriteCssClassField", imageUrl: "dataImageUrlField", imageAttr: "dataImageAttrField", content: "dataContentField" }, rendering = { wrapperCssClass: function(group, item) { var result = "k-item k-menu-item", index = item.index; if (item.separator) { result += " k-separator"; } if (item.enabled === false) { result += " k-disabled"; } if (group.firstLevel && index === 0) { result += " k-first"; } if (index == group.length - 1) { result += " k-last"; } if (item.cssClass) { result += " " + item.cssClass; } if (item.attr && item.attr.hasOwnProperty("class")) { result += " " + item.attr["class"]; } if (item.selected) { result += " " + SELECTEDSTATE; } return result; }, itemCssAttributes: function(item) { var result = ""; var attributes = item.attr || {}; for (var attr in attributes) { if (attributes.hasOwnProperty(attr) && attr !== "class") { result += attr + "=\"" + attributes[attr] + "\" "; } } return result; }, imageCssAttributes: function(imgAttributes) { var result = ""; var attributes = imgAttributes && imgAttributes.toJSON ? imgAttributes.toJSON() : {}; if (!attributes['class']) { attributes['class'] = IMAGE; } else { attributes['class'] += " " + IMAGE; } for (var attr in attributes) { if (attributes.hasOwnProperty(attr)) { result += attr + "=\"" + attributes[attr] + "\" "; } } return result; }, contentCssAttributes: function(item) { var result = ""; var attributes = item.contentAttr || {}; var defaultClasses = "k-content k-menu-group k-menu-group-md"; if (!attributes['class']) { attributes['class'] = defaultClasses; } else { attributes['class'] += " " + defaultClasses; } for (var attr in attributes) { if (attributes.hasOwnProperty(attr)) { result += attr + "=\"" + attributes[attr] + "\" "; } } return result; }, textClass: function() { return LINK; }, groupAttributes: function(group) { return group.expanded !== true ? `${kendo.attr("style-display")}="none"` : ""; }, groupCssClass: function() { return "k-menu-group k-menu-group-md"; }, groupWrapperCssClass: function() { return "k-menu-popup"; }, content: function(item) { return item.content ? item.content : "&nbsp;"; } }; function getEffectDirection(direction, root) { direction = direction.split(" ")[!root + 0] || direction; return direction.replace("top", "up").replace("bottom", "down"); } function parseDirection(direction, root, isRtl) { direction = direction.split(" ")[!root + 0] || direction; var output = { origin: ["bottom", (isRtl ? "right" : "left")], position: ["top", (isRtl ? "right" : "left")] }, horizontal = /left|right/.test(direction); if (horizontal) { output.origin = [ "top", direction ]; output.position[1] = kendo.directions[direction].reverse; } else { output.origin[0] = direction; output.position[0] = kendo.directions[direction].reverse; } output.origin = output.origin.join(" "); output.position = output.position.join(" "); return output; } function contains(parent, child) { try { return $.contains(parent, child); } catch (e) { return false; } } function updateItemClasses(item) { item = $(item); var omitWrap = item.attr(kendo.attr("omit-wrap")); if (omitWrap) { return; } item.addClass("k-item k-menu-item") .children(IMG) .addClass(IMAGE); item .children("a") .addClass(LINK) .children(IMG) .addClass(IMAGE); item .filter(":not([disabled])"); item .filter(".k-separator") .removeClass("k-menu-item") .addClass("k-menu-separator") .empty() .append("&nbsp;"); item .filter("li[disabled]") .addClass(DISABLEDSTATE) .prop("disabled", false) .attr("aria-disabled", true); if (!item.filter("[role]").length) { item.attr(ROLE, "menuitem"); } if (!item.children(LINK_SELECTOR).length) { item.contents() // exclude groups, real links, templates and empty text nodes .filter(function() { return (!this.nodeName.match(excludedNodesRegExp) && !(this.nodeType === 3 && !kendo.trim(this.nodeValue))); }) // adding role=none to span elements inside li[role=menuitem] // to make screen readers announce submenus #telerik/kendo-ui-core/issues/6942 .wrapAll("<span class='" + LINK + "' role='none'></span>") .filter(function(idx, elm) { return elm.nodeType === 3; }) .wrap("<span class='k-menu-link-text' role='none'></span>"); } updateArrow(item); updateFirstLast(item); } function updateArrow(item) { item = $(item); item.find("> .k-link > .k-menu-expand-arrow > [class*=k-i-caret]:not(.k-sprite),> .k-link > .k-menu-expand-arrow > [class*=k-svg-i-caret]:not(.k-sprite)").parent().remove(); item.filter(":has(.k-menu-group)") .children(".k-link:not(:has([class*=k-i-caret]:not(.k-sprite))),.k-link:not(:has([class*=k-svg-i-caret]:not(.k-sprite)))") .each(function() { var item = $(this); item.append(`<span aria-hidden='true' class='k-menu-expand-arrow'>${kendo.ui.icon({ icon: getArrowIconName(item) })}</span>`); }); } function getArrowIconName(item) { var arrowIconName, parent = item.parent().parent(), isRtl = kendo.support.isRtl(parent); if (parent.hasClass(MENU + "-horizontal")) { arrowIconName = "caret-alt-down"; } else { if (isRtl) { arrowIconName = "caret-alt-left"; } else { arrowIconName = "caret-alt-right"; } } return arrowIconName; } function updateFirstLast(item) { item = $(item); item.filter(".k-first:not(:first-child)").removeClass(FIRST); item.filter(".k-last:not(:last-child)").removeClass(LAST); item.filter(":first-child").addClass(FIRST); item.filter(":last-child").addClass(LAST); } function updateHasAriaPopup(parents) { if (parents && parents.length) { for (var index in parents) { var parentLi = parents.eq(index); if (parentLi.find("ul").length) { parentLi.attr("aria-haspopup", true); } else { parentLi.removeAttr("aria-haspopup"); } } } } function getParentLiItems(group) { if (!group.hasClass(MENU)) { return group.parentsUntil("." + MENU, "li"); } } function storeItemSelectEventHandler(element, options) { var selectHandler = getItemSelectEventHandler(options); if (selectHandler) { setItemData(element, selectHandler); } if (options.items) { $(element).children("div").children("ul").children("li").each(function(i) { storeItemSelectEventHandler(this, options.items[i]); }); } } function setItemData(element, selectHandler) { $(element).children(".k-link").data({ selectHandler: selectHandler }); } function getItemSelectEventHandler(options) { var selectHandler = options.select, isFunction = kendo.isFunction; if (selectHandler && isFunction(selectHandler)) { return selectHandler; } return null; } function popupOpenerSelector(id) { return id ? "li[data-groupparent='" + id + "']" : "li[data-groupparent]"; } function popupGroupSelector(id) { var selector = id ? "[data-group='" + id + "']" : "[data-group]"; return "ul" + selector + ",div" + selector; } function getChildPopups(currentPopup, overflowWrapper) { var childPopupOpener = currentPopup.find(popupOpenerSelector()); var result = []; childPopupOpener.each(function(i, opener) { opener = $(opener); var popupId = opener.data(POPUP_OPENER_ATTR); var popup = currentPopup; while (popupId) { popup = overflowWrapper.find(popupGroupSelector(popupId) + ":visible"); if (popup.length) { result.push(popup); } opener = popup.find(popupOpenerSelector()); popupId = opener.data(POPUP_OPENER_ATTR); } }); return result; } function popupParentItem(popupElement, overflowWrapper) { var popupId = popupElement.data(POPUP_ID_ATTR); return popupId ? overflowWrapper.find(popupOpenerSelector(popupId)) : $([]); } function itemPopup(item, overflowWrapper) { var popupId = item.data(POPUP_OPENER_ATTR); return popupId ? overflowWrapper.children(animationContainerSelector).find(popupGroupSelector(popupId)) : $([]); } function overflowMenuParents(current, overflowWrapper) { var parents = []; var getParents = function(item) { while (item.parentNode && !overflowWrapper.is(item.parentNode)) { parents.push(item.parentNode); item = item.parentNode; } }; var elem = current[0] || current; getParents(elem); var last = parents[parents.length - 1]; while ($(last).is(animationContainerSelector)) { var popupElement = $(last).find(popupSelector); elem = popupParentItem(popupElement, overflowWrapper)[0]; if (!elem) { break; } parents.push(elem); getParents(elem); last = parents[parents.length - 1]; } return parents; } function mousewheelDelta(e) { var delta = 0; if (e.wheelDelta) { delta = -e.wheelDelta / 120; delta = delta > 0 ? Math.ceil(delta) : Math.floor(delta); } if (e.detail) { delta = Math.round(e.detail / 3); } return delta; } function parentsScroll(current, scrollDirection) { var scroll = 0; var parent = current.parentNode; while (parent && !isNaN(parent[scrollDirection])) { scroll += parent[scrollDirection]; parent = parent.parentNode; } return scroll; } function isPointerTouch(e) { return allPointers && e.originalEvent && e.originalEvent.pointerType in touchPointerTypes; } function isTouch(e) { var ev = e.originalEvent; return touch && /touch/i.test(ev.type || ""); } function removeSpacesBetweenItems(ul) { ul.contents().filter(function() { return this.nodeName != "LI"; }).remove(); } var Menu = kendo.ui.DataBoundWidget.extend({ init: function(element, options) { var that = this; Widget.fn.init.call(that, element, options); element = that.wrapper = that.element; options = that.options; that._accessors(); that._templates(); that._dataSource(); that._updateClasses(); that._wrapGroups(); that._animations(options); that.nextItemZIndex = 100; that._tabindex(); that._initOverflow(options); that._attachMenuEventsHandlers(); if (options.openOnClick) { that.clicked = false; } element.attr(ROLE, "menubar"); if (element[0].id) { that._ariaId = kendo.format("{0}_mn_active", element[0].id); } else { that._ariaId = kendo.format("{0}_mn_active", kendo.guid()); } kendo.notify(that); }, events: [ OPEN, CLOSE, ACTIVATE, DEACTIVATE, SELECT, DATABOUND ], options: { name: "Menu", animation: { open: { duration: 200 }, close: { // if close animation effects are defined, they will be used instead of open.reverse duration: 100 } }, orientation: "horizontal", direction: "default", openOnClick: false, closeOnClick: true, hoverDelay: 100, scrollable: false, popupCollision: null, autoSize: false, }, _initData: function() { var that = this; if (that.dataSource) { that.element.empty(); that.append(that.dataSource.view(), that.element); } }, _attachMenuEventsHandlers: function() { var that = this; var element = that.element; var options = that.options; var overflowWrapper = that._overflowWrapper(); that._checkActiveProxy = that._checkActiveElement.bind(that); (overflowWrapper || element).on(POINTERDOWN, itemSelector, that._focusHandler.bind(that)) .on(CLICK + NS, disabledSelector, false) .on(CLICK + NS, itemSelector, that._click.bind(that)) .on(POINTERDOWN + " " + MOUSEDOWN + NS, ".k-content", that._preventClose.bind(that)) .on(MOUSEENTER + NS, availableItemsSelector, that._mouseenter.bind(that)) .on(MOUSELEAVE + NS, availableItemsSelector, that._mouseleave.bind(that)) .on(MOUSEDOWN + NS, availableItemsSelector, that._mousedown.bind(that)) .on(TOUCHSTART + NS + " " + MOUSEENTER + NS + " " + MOUSELEAVE + NS + " " + MOUSEDOWN + NS + " " + CLICK + NS, linkSelector, that._toggleHover.bind(that)); element.on("keydown" + NS, that._keydown.bind(that)) .on("focus" + NS, that._focus.bind(that)) .on("focus" + NS, ".k-content", that._focus.bind(that)) .on("blur" + NS, that._removeFocusItem.bind(that)) .on("blur" + NS, "[tabindex]", that._checkActiveProxy); if (overflowWrapper) { overflowWrapper .on(MOUSELEAVE + NS, popupSelector, that._mouseleavePopup.bind(that)) .on(MOUSEENTER + NS, popupSelector, that._mouseenterPopup.bind(that)); } if (options.openOnClick) { that._documentClickHandler = that._documentClick.bind(that); $(document).on("click", that._documentClickHandler); } }, _detachMenuEventsHandlers: function() { var that = this; var overflowWrapper = that._overflowWrapper(); if (overflowWrapper) { overflowWrapper.off(NS); } that.element.off(NS); if (that._documentClickHandler) { $(document).off("click", that._documentClickHandler); } }, _getNeededSpaceForChildren: function(element, horizontal) { const children = element.children(); let total = 0; if (children.length > 0) { children.each((_, element) => { if (horizontal) { total += kendo._outerWidth(element); } else { total += kendo._outerHeight(element); } }); } return total; }, _initOverflow: function(options) { var that = this; var isHorizontal = options.orientation == "horizontal"; var backwardBtn, forwardBtn; const isRtl = kendo.support.isRtl(that.wrapper); that._openedPopups = {}; if (options.scrollable) { that._scrollWrapper = that.element.wrap(`<div class="k-menu-scroll-wrapper${options.orientation === 'vertical' ? " k-menu-scroll-wrapper-vertical" : ""}"></div>`).parent(); if (isHorizontal) { removeSpacesBetweenItems(that.element); } let backwardBtnIcon = isHorizontal ? (isRtl ? 'right' : 'left') : 'up'; let forwardBtnIcon = isHorizontal ? (isRtl ? 'left' : 'right') : 'down'; backwardBtn = $(that.templates.scrollButton({ direction: backwardBtnIcon })); forwardBtn = $(that.templates.scrollButton({ direction: forwardBtnIcon })); backwardBtn.prependTo(that._scrollWrapper); forwardBtn.appendTo(that._scrollWrapper); that._initScrolling(that.element, backwardBtn, forwardBtn, isHorizontal, isRtl); var initialWidth = that.element.outerWidth(); var initialCssWidth = that.element[0].style.width; initialCssWidth = initialCssWidth === "auto" ? "" : initialCssWidth; if (isHorizontal) { $(window).on(RESIZE, function() { setTimeout(function() { that._setOverflowWrapperWidth(initialWidth, initialCssWidth); that._toggleScrollButtons(that.element, backwardBtn, forwardBtn, isHorizontal); }, 300); }); } that._setOverflowWrapperWidth(initialWidth, initialCssWidth); that._toggleScrollButtons(that.element, backwardBtn, forwardBtn, isHorizontal); } }, _overflowWrapper: function() { return this._scrollWrapper || this._popupsWrapper; }, _setOverflowWrapperWidth: function(initialWidth, initialCssWidth) { var that = this; var wrapperCssWidth = that._scrollWrapper.css("width"); that._scrollWrapper.css({ width: "" }); var wrapperWidth = that._scrollWrapper.outerWidth(); that._scrollWrapper.css({ width: wrapperCssWidth }); var menuWidth = that.element.outerWidth(); var borders = that.element[0].offsetWidth - that.element[0].clientWidth; if (menuWidth != wrapperWidth && wrapperWidth > 0) { var width = initialCssWidth ? Math.min(initialWidth, wrapperWidth) : wrapperWidth; that.element.width(width - borders); that._scrollWrapper.width(width); } }, _reinitOverflow: function(options) { var that = this; var overflowChanged = ((options.scrollable && !that.options.scrollable) || (!options.scrollable && that.options.scrollable)) || (options.scrollable && that.options.scrollable && options.scrollable.distance != that.options.scrollable.distance) || options.orientation != that.options.orientation; if (overflowChanged) { that._detachMenuEventsHandlers(); that._destroyOverflow(); that._initOverflow(options); that._attachMenuEventsHandlers(); } }, _destroyOverflow: function() { var that = this; var overflowWrapper = that._overflowWrapper(); if (overflowWrapper) { overflowWrapper.off(NS); overflowWrapper.find(scrollButtonSelector).off(NS).remove(); overflowWrapper.children(animationContainerSelector).each(function(i, popupWrapper) { var ul = $(popupWrapper).find(".k-child-animation-container > .k-menu-popup"); ul.off(MOUSEWHEEL); var popupParentLi = popupParentItem(ul, overflowWrapper); if (popupParentLi.length) { popupParentLi.append(popupWrapper); } }); overflowWrapper.find(popupOpenerSelector()).removeAttr("data-groupparent"); overflowWrapper.find(popupGroupSelector()).removeAttr("data-group"); that.element.off(MOUSEWHEEL); $(window).off(RESIZE); overflowWrapper.contents().unwrap(); that._scrollWrapper = that._popupsWrapper = that._openedPopups = undefined$1; } }, _initScrolling: function(scrollElement, backwardBtn, forwardBtn, isHorizontal, isRtl) { var that = this; var scrollable = that.options.scrollable; var distance = that.isNumeric(scrollable.distance) ? scrollable.distance : SCROLLSPEED; var mouseWheelDistance = distance / 2; var backward = "-=" + distance; var forward = "+=" + distance; var backwardDouble = "-=" + distance * 2; var forwardDouble = "+=" + distance * 2; var scrolling = false; var touchEvents = false; var scroll = function(value) { var scrollValue = isHorizontal ? { "scrollLeft": value } : { "scrollTop": value }; scrollElement.finish().animate(scrollValue, "fast", "linear", function() { if (scrolling) { scroll(value); } }); that._toggleScrollButtons(scrollElement, backwardBtn, forwardBtn, isHorizontal, isRtl); }; var mouseenterHandler = function(e) { if (!scrolling && !touchEvents) { scroll(e.data.direction); scrolling = true; } }; var mousedownHandler = function(e) { var scrollValue = isHorizontal ? { "scrollLeft": e.data.direction } : { "scrollTop": e.data.direction }; touchEvents = isTouch(e) || isPointerTouch(e); scrollElement.stop().animate(scrollValue, "fast", "linear", function() { if (!touchEvents) { $(e.currentTarget).trigger(MOUSEENTER); } else { that._toggleScrollButtons(scrollElement, backwardBtn, forwardBtn, isHorizontal, isRtl); scrolling = true; } }); scrolling = false; e.stopPropagation(); e.preventDefault(); }; backwardBtn.on(MOUSEENTER + NS, { direction: isRtl && isHorizontal ? forward : backward }, mouseenterHandler) .on(kendo.eventMap.down + NS, { direction: isRtl && isHorizontal ? forwardDouble : backwardDouble }, mousedownHandler); forwardBtn.on(MOUSEENTER + NS, { direction: isRtl && isHorizontal ? backward : forward }, mouseenterHandler) .on(kendo.eventMap.down + NS, { direction: isRtl && isHorizontal ? backwardDouble : forwardDouble }, mousedownHandler); backwardBtn.add(forwardBtn) .on(MOUSELEAVE + NS, function() { scrollElement.stop(); scrolling = false; that._toggleScrollButtons(scrollElement, backwardBtn, forwardBtn, isHorizontal, isRtl); }); scrollElement.on(MOUSEWHEEL, function(e) { if (!e.ctrlKey && !e.shiftKey && !e.altKey) { var wheelDelta = mousewheelDelta(e.originalEvent); var scrollSpeed = Math.abs(wheelDelta) * mouseWheelDistance; var value = (wheelDelta > 0 ? "+=" : "-=") + scrollSpeed; var scrollValue = isHorizontal ? { "scrollLeft": value } : { "scrollTop": value }; that._closeChildPopups(scrollElement); scrollElement.finish().animate(scrollValue, "fast", "linear", function() { that._toggleScrollButtons(scrollElement, backwardBtn, forwardBtn, isHorizontal); }); e.preventDefault(); } }); }, isNumeric: function(n) { return !isNaN(parseFloat(n)) && isFinite(n); }, _toggleScrollButtons: function(scrollElement, backwardBtn, forwardBtn, horizontal) { const neededSpace = this._getNeededSpaceForChildren(scrollElement, horizontal); const elementSpace = horizontal ? kendo._outerWidth(this.element) : kendo._outerHeight(this.element); backwardBtn.toggle(neededSpace > elementSpace); forwardBtn.toggle(neededSpace > elementSpace); const currentScroll = horizontal ? kendo.scrollLeft(scrollElement) : scrollElement.scrollTop(); const elementIsPopup = scrollElement.is(popupSelector) || scrollElement.parent().is(childAnimationContainerSelector); let disableNextButton = Math.abs(currentScroll - (scrollElement[0].scrollWidth - scrollElement[0].offsetWidth)) <= 1; if (!horizontal) { disableNextButton = Math.abs(currentScroll - (scrollElement[0].scrollHeight - scrollElement[0].offsetHeight)) <= 1; } if (elementIsPopup) { disableNextButton = Math.abs(currentScroll - (scrollElement[0].scrollHeight - scrollElement[0].offsetHeight) - 1) <= 1; } backwardBtn.toggleClass(DISABLEDSTATE, Math.floor(currentScroll) === 0); forwardBtn.toggleClass(DISABLEDSTATE, disableNextButton); }, setOptions: function(options) { var animation = this.options.animation; this._animations(options); options.animation = extend(true, animation, options.animation); if ("dataSource" in options) { this._dataSource(options); } this._updateClasses(); this._wrapGroups(); this._reinitOverflow(options); Widget.fn.setOptions.call(this, options); }, destroy: function() { var that = this; Widget.fn.destroy.call(that); that._detachMenuEventsHandlers(); that._destroyOverflow(); kendo.destroy(that.element); }, enable: function(element, enable) { this._toggleDisabled(element, enable !== false); return this; }, disable: function(element) { this._toggleDisabled(element, false); return this; }, attemptGetItem: function(candidate) { candidate = candidate || this.element; var item = this.element.find(candidate); var overflowWrapper = this._overflowWrapper(); if (item.length || candidate === this.element) { return item; } else if (overflowWrapper) { return overflowWrapper.find(candidate); } else { return $(); } }, append: function(item, referenceItem) { referenceItem = this.attemptGetItem(referenceItem); var inserted = this._insert(item, referenceItem, referenceItem.length ? this._childPopupElement(referenceItem).children().eq(0) : null); each(inserted.items, function(i) { inserted.group.append(this); updateArrow(this); storeItemSelectEventHandler(this, item[i] || item); }); updateArrow(referenceItem); updateFirstLast(inserted.group.find(".k-first, .k-last").add(inserted.items)); updateHasAriaPopup(getParentLiItems(inserted.group)); return this; }, insertBefore: function(item, referenceItem) { referenceItem = this.attemptGetItem(referenceItem); var inserted = this._insert(item, referenceItem, referenceItem.parent()); each(inserted.items, function(i) { referenceItem.before(this); updateArrow(this); updateFirstLast(this); storeItemSelectEventHandler(this, item[i] || item); }); updateFirstLast(referenceItem); return this; }, insertAfter: function(item, referenceItem) { referenceItem = this.attemptGetItem(referenceItem); var inserted = this._insert(item, referenceItem, referenceItem.parent()); each(inserted.items, function(i) { referenceItem.after(this); updateArrow(this); updateFirstLast(this); storeItemSelectEventHandler(this, item[i] || item); }); updateFirstLast(referenceItem); return this; }, _insert: function(item, referenceItem, parent) { var that = this, items, groups; if (!referenceItem || !referenceItem.length) { parent = that.element; } var plain = $.isPlainObject(item) || item instanceof kendo.data.ObservableObject, groupData = { firstLevel: parent.hasClass(MENU), horizontal: parent.hasClass(MENU + "-horizontal"), expanded: true, length: parent.children().length }; if (referenceItem && !parent.length) { parent = $(that.renderGroup({ group: groupData, options: that.options })).css("display", "none").appendTo(referenceItem); kendo.applyStylesFromKendoAttributes(parent, ["display"]); } if (plain || isArray(item) || item instanceof kendo.data.ObservableArray) { // is JSON items = $($.map(plain ? [ item ] : item, function(value, idx) { if (typeof value === "string") { return $(value).get(); } else { let itemElement = $(that.renderItem({ group: groupData, item: extend(value, { index: idx }) })); kendo.applyStylesFromKendoAttributes(itemElement, ["display"]); return itemElement.get(); } })); } else { if (typeof item == "string" && item.charAt(0) != "<") { items = that.element.find(item); } else { items = $(item); } groups = items.find("> ul") .addClass("k-menu-group k-menu-group-md") .attr(ROLE, "menu"); items = items.filter("li"); items.add(groups.find("> li")).each(function() { updateItemClasses(this); }); } parent = parent.is(popupSelector) ? parent.find(groupSelector).first() : parent; return { items: items, group: parent }; }, remove: function(element) { element = this.attemptGetItem(element); var that = this, parent = element.parentsUntil(that.element, allItemsSelector), group = element.parent("ul:not(.k-menu)"); element.remove(); if (group && !group.children(allItemsSelector).length) { var parentItems = getParentLiItems(group); var container = group.parent(animationContainerSelector); if (container.length) { container.remove(); } else { group.remove(); } updateHasAriaPopup(parentItems); } if (parent.length) { parent = parent.eq(0); updateArrow(parent); updateFirstLast(parent); } return that; }, _openAfterLoad: function(element, dataItem) { var that = this; if (dataItem.loaded()) { that.open(element); that._loading = false; } else { dataItem.one(CHANGE, function() { element.find(ICON_SELECTOR).children().removeClass("k-i-loading"); if (that._loading) { that.open(element); that._loading = false; } }); } }, _createPopup: function(div, options) { let that = this; let overflowWrapper = that._overflowWrapper(); return div.kendoPopup(extend({ activate: function() { that._triggerEvent({ item: this.wrapper.parent(), type: ACTIVATE }); }, deactivate: function(e) { that._closing = false; e.sender.element // Restore opacity after fade. .removeData("targetTransform") .css({ opacity: "" }); that._triggerEvent({ item: this.wrapper.parent(), type: DEACTIVATE }); }, open: that._popupOpen.bind(that), close: function(e) { that._closing = e.sender.element; var li = e.sender.wrapper.parent(); if (overflowWrapper) { var popupId = e.sender.element.data(POPUP_ID_ATTR); if (popupId) { li = (overflowWrapper || that.element).find(popupOpenerSelector(popupId)); } e.sender.wrapper.children(scrollButtonSelector).hide(); } if (!that._triggerEvent({ item: li[0], type: CLOSE })) { li.css(ZINDEX, li.data(ZINDEX)); li.removeData(ZINDEX); if (that.options.scrollable) { li.parent().siblings(scrollButtonSelector).css({ zIndex: "" }); } if (touch || allPointers || kendo.support.mouseAndTouchPresent) { li.removeClass(HOVERSTATE); } } else { e.preventDefault(); } } }, options)).data(KENDOPOPUP); }, open: function(element) { var that = this; var options = that.options; var horizontal = options.orientation == "horizontal"; var direction = options.direction; var isRtl = kendo.support.isRtl(that.wrapper); var overflowWrapper = that._overflowWrapper(); element = (overflowWrapper || that.element).find(element); var dataItem = that.dataSource && that.dataSource.getByUid(element.data(kendo.ns + "uid")); if (dataItem && dataItem.hasChildren && !dataItem.loaded() && !that._loading) { that._loading = true; element.find(ICON_SELECTOR).children().addClass("k-i-loading"); dataItem.load(); that._openAfterLoad(element, dataItem); return; } if (/^(top|bottom|default)$/.test(direction)) { if (isRtl) { direction = horizontal ? (direction + " left").replace("default", "bottom") : "left"; } else { direction = horizontal ? (direction + " right").replace("default", "bottom") : "right"; } } var visiblePopups = ">.k-popup:visible,>.k-animation-container > .k-child-animation-container > .k-menu-popup:visible"; var closePopup = function() { var popup = $(this).data(KENDOPOPUP); if (popup) { // Use the built-in close method to play the hoverDelay from the options that.close($(this).closest("li.k-item"), true); } }; element.siblings() .find(visiblePopups) .each(closePopup); if (overflowWrapper) { element.find(visiblePopups).each(closePopup); } if (that.options.openOnClick) { that.clicked = true; } element.each(function() { var li = $(this); clearTimeout(li.data(TIMER)); clearTimeout(that._timerTimeout); that._timerTimeout = setTimeout(function() { var div = li.find("> .k-menu-popup, > .k-animation-container > .k-child-animation-container > .k-menu-popup").filter(":hidden").first(); var popup; var overflowPopup; if (!div[0] && overflowWrapper) { overflowPopup = that._getPopup(li); div = overflowPopup && overflowPopup.element; } if (div.is(":visible")) { return; } if (div[0] && that._triggerEvent({ item: li[0], type: OPEN }) === false) { const menuParent = div.children('.k-menu-scroll-wrapper').length ? div.children('.k-menu-scroll-wrapper') : div; const menu = that._groupElementsInitialSpace.find(({ element }) => menuParent.children('ul').is(element)); let maxHeight = ""; if (menu && Object.keys(menu).length > 0) { if (menu.height > 0) { maxHeight = menu.height; } that._popupToBeOpened = menu; if (menu.inlineHeight) { $(menu.element).css({ height: menu.inlineHeight }); } else { $(menu.element).css({ height: "" }); } } const maxWidthNone = options.scrollable || options.autoSize; const overflow = options.autoSize ? "auto" : "visible"; div.css({ maxHeight: maxWidthNone ? "" : maxHeight, overflow: overflow }); li.data(ZINDEX, li.css(ZINDEX)); var nextZindex = that.nextItemZIndex++; li.css(ZINDEX, nextZindex); if (that.options.scrollable) { li.parent().siblings(scrollButtonSelector).css({ zIndex: ++nextZindex }); } popup = div.data(KENDOPOPUP); var root = li.parent().hasClass(MENU), parentHorizontal = root && horizontal, directions = parseDirection(direction, root, isRtl), effects = options.animation.open.effects, openEffects = effects !== undefined$1 ? effects : "slideIn:" + getEffectDirection(direction, root), collision; if (options.popupCollision !== null) { collision = options.popupCollision; } else if (parentHorizontal) { collision = "fit"; } else { collision = "fit flip"; } if (!popup) { popup = that._createPopup(div, { origin: directions.origin, position: directions.position, collision: collision, anchor: li, appendTo: overflowWrapper || li, animation: { open: extend(true, { effects: openEffects }, options.animation.open), close: options.animation.close }, }); div.closest(animationContainerSelector).removeAttr(ROLE); } else { popup = div.data(KENDOPOPUP); popup.options.origin = directions.origin; popup.options.position = directions.position; popup.options.animation.open.effects = openEffects; } div.removeAttr("aria-hidden"); li.attr(ARIA_EXPANDED, true); that._configurePopupOverflow(popup, li); popup._hovered = true; popup.open(); that._initPopupScrolling(popup); } }, that.options.hoverDelay); li.data(TIMER, that._timerTimeout); }); return that; }, _configurePopupOverflow: function(popup, popupOpener) { var that = this; if (that.options.scrollable) { that._wrapPopupElement(popup); if (!popupOpener.attr("data-groupparent")) { var groupId = new Date().getTime(); popupOpener.attr("data-groupparent", groupId); popup.element.attr("data-group", groupId); } } }, _wrapPopupElement: function(popup) { if (!popup.element.parent().is(childAnimationContainerSelector)) { popup.wrapper = kendo.wrap(popup.element, popup.options.autosize) .css({ overflow: "hidden", display: "block", position: "absolute" }); } }, _initPopupScrolling: function(popup, isHorizontal, skipMouseEvents) { var that = this; const popupElement = popup.element; const scrollWrapper = popupElement.children('.k-menu-scroll-wrapper'); const menu = scrollWrapper.length ? $(scrollWrapper.children('ul')) : $(popupElement.children('ul')); let childrenScrollSpace = that._getNeededSpaceForChildren(menu, isHorizontal); let initScrolling = false; if (isHorizontal) { initScrolling = (kendo._outerWidth(popupElement) < childrenScrollSpace); } else { initScrolling = (kendo._outerHeight(popupElement) < childrenScrollSpace); } if (that.options.scrollable && ((popupElement[0].scrollHeight > popupElement[0].offsetHeight) || initScrolling)) { that._initPopupScrollButtons(popup, isHorizontal, skipMouseEvents); } else { if (scrollWrapper.length) { scrollWrapper.find(scrollButtonSelector).remove(); menu.unwrap(); } } }, _scrollButtonsMouseEnter: function() { let that = this; let popup = that.popup; let overflowWrapper = that._overflowWrapper(); $(getChildPopups(popup.element, overflowWrapper)).each(function(i, p) { let popupOpener = overflowWrapper.find(popupOpenerSelector(p.data(POPUP_ID_ATTR))); that.close(popupOpener); }); }, _scrollButtonsMouseLeave: function() { let that = this; let popup = that.popup; setTimeout(function() { if ($.isEmptyObject(that._openedPopups)) { that._closeParentPopups(popup.element); } }, DELAY); }, _initPopupScrollButtons: function(popup, isHorizontal, skipMouseEvents) { let that = this, scrollButtons = popup.wrapper.find(scrollButtonSelector), element = popup.element, scrollWrapper = element.children('.k-menu-scroll-wrapper'), menu = element.children('ul'); that._denyOpening = true; if (!menu.length && scrollWrapper.length) { menu = scrollWrapper.childre