mirror of
https://github.com/layui/layui.git
synced 2026-02-09 02:09:18 +08:00
689 lines
21 KiB
JavaScript
689 lines
21 KiB
JavaScript
import { layui } from '../core/layui.js';
|
||
import { lay } from '../core/lay.js';
|
||
import { i18n } from '../core/i18n.js';
|
||
import $ from 'jquery';
|
||
import { laytpl } from '../core/laytpl.js';
|
||
import { util } from './util.js';
|
||
|
||
/**
|
||
* dropdown
|
||
* 下拉菜单组件
|
||
*/
|
||
|
||
var device = layui.device();
|
||
var clickOrMousedown = device.mobile ? 'touchstart' : 'mousedown';
|
||
|
||
// 模块名
|
||
var MOD_NAME = 'dropdown';
|
||
var MOD_INDEX = 'layui_' + MOD_NAME + '_index'; // 模块索引名
|
||
var MOD_INDEX_OPENED = MOD_INDEX + '_opened';
|
||
var MOD_ID = 'lay-' + MOD_NAME + '-id';
|
||
var resizeObserver = lay.createSharedResizeObserver(MOD_NAME);
|
||
|
||
// 外部接口
|
||
var dropdown = {
|
||
config: {
|
||
customName: {
|
||
// 自定义 data 字段名
|
||
id: 'id',
|
||
title: 'title',
|
||
children: 'child'
|
||
}
|
||
},
|
||
// 设置全局项
|
||
set: function (options) {
|
||
var that = this;
|
||
that.config = $.extend({}, that.config, options);
|
||
return that;
|
||
},
|
||
// 事件
|
||
on: function (events, callback) {
|
||
return layui.onevent.call(this, MOD_NAME, events, callback);
|
||
}
|
||
};
|
||
|
||
// 操作当前实例
|
||
var thisModule = function () {
|
||
var that = this;
|
||
var options = that.config;
|
||
var id = options.id;
|
||
return {
|
||
config: options,
|
||
// 重置实例
|
||
reload: function (options) {
|
||
that.reload.call(that, options);
|
||
},
|
||
reloadData: function (options) {
|
||
dropdown.reloadData(id, options);
|
||
},
|
||
close: function () {
|
||
that.remove();
|
||
},
|
||
open: function () {
|
||
that.render();
|
||
}
|
||
};
|
||
};
|
||
|
||
// 字符常量
|
||
var STR_ELEM = 'layui-dropdown';
|
||
var STR_DISABLED = 'layui-disabled';
|
||
var STR_ITEM_UP = 'layui-menu-item-up';
|
||
var STR_ITEM_DOWN = 'layui-menu-item-down';
|
||
var STR_MENU_TITLE = 'layui-menu-body-title';
|
||
var STR_ITEM_GROUP = 'layui-menu-item-group';
|
||
var STR_ITEM_PARENT = 'layui-menu-item-parent';
|
||
var STR_ITEM_DIV = 'layui-menu-item-divider';
|
||
var STR_ITEM_CHECKED = 'layui-menu-item-checked';
|
||
var STR_ITEM_CHECKED2 = 'layui-menu-item-checked2';
|
||
var STR_MENU_PANEL = 'layui-menu-body-panel';
|
||
var STR_MENU_PANEL_L = 'layui-menu-body-panel-left';
|
||
var STR_ELEM_SHADE = 'layui-dropdown-shade';
|
||
var STR_GROUP_TITLE = '.' + STR_ITEM_GROUP + '>.' + STR_MENU_TITLE;
|
||
|
||
// 构造器
|
||
var Class = function (options) {
|
||
var that = this;
|
||
that.index = dropdown.index = lay.autoIncrementer('dropdown');
|
||
that.config = $.extend({}, that.config, dropdown.config, options);
|
||
that.stopClickOutsideEvent = $.noop;
|
||
that.stopResizeEvent = $.noop;
|
||
that.init();
|
||
};
|
||
|
||
// 默认配置
|
||
Class.prototype.config = {
|
||
trigger: 'click',
|
||
// 事件类型
|
||
content: '',
|
||
// 自定义菜单内容
|
||
className: '',
|
||
// 自定义样式类名
|
||
style: '',
|
||
// 设置面板 style 属性
|
||
show: false,
|
||
// 是否初始即显示菜单面板
|
||
isAllowSpread: true,
|
||
// 是否允许菜单组展开收缩
|
||
isSpreadItem: true,
|
||
// 是否初始展开子菜单
|
||
data: [],
|
||
// 菜单数据结构
|
||
delay: [200, 300],
|
||
// 延时显示或隐藏的毫秒数,若为 number 类型,则表示显示和隐藏的延迟时间相同,trigger 为 hover 时才生效
|
||
shade: 0,
|
||
// 遮罩
|
||
accordion: false,
|
||
// 手风琴效果,仅菜单组生效。基础菜单需要在容器上追加 'lay-accordion' 属性。
|
||
closeOnClick: true // 面板打开后,再次点击目标元素时是否关闭面板。行为取决于所使用的触发事件类型
|
||
};
|
||
|
||
// 重载实例
|
||
Class.prototype.reload = function (options, type) {
|
||
var that = this;
|
||
that.config = $.extend({}, that.config, options);
|
||
that.init(true, type);
|
||
};
|
||
|
||
// 初始化准备
|
||
Class.prototype.init = function (rerender, type) {
|
||
var that = this;
|
||
var options = that.config;
|
||
|
||
// 若 elem 非唯一
|
||
var elem = $(options.elem);
|
||
if (elem.length > 1) {
|
||
layui.each(elem, function () {
|
||
dropdown.render($.extend({}, options, {
|
||
elem: this
|
||
}));
|
||
});
|
||
return that;
|
||
}
|
||
|
||
// 合并 lay-options 属性上的配置信息
|
||
$.extend(options, lay.options(elem[0]));
|
||
|
||
// 若重复执行 render,则视为 reload 处理
|
||
if (!rerender && elem.attr(MOD_ID)) {
|
||
var newThat = thisModule.getThis(elem.attr(MOD_ID));
|
||
if (!newThat) return;
|
||
return newThat.reload(options, type);
|
||
}
|
||
options.elem = $(options.elem);
|
||
options.target = $('body'); // 后续考虑开放 target 元素
|
||
|
||
// 初始化 id 属性 - 优先取 options > 元素 id > 自增索引
|
||
options.id = 'id' in options ? options.id : elem.attr('id') || that.index;
|
||
thisModule.that[options.id] = that; // 记录当前实例对象
|
||
elem.attr(MOD_ID, options.id); // 目标元素已渲染过的标记
|
||
|
||
// 初始化自定义字段名
|
||
options.customName = $.extend({}, dropdown.config.customName, options.customName);
|
||
|
||
// 若传入 hover,则解析为 mouseenter
|
||
if (options.trigger === 'hover') {
|
||
options.trigger = 'mouseenter';
|
||
}
|
||
|
||
// 初始即显示或者面板弹出之后执行了刷新数据
|
||
if (options.show || type === 'reloadData' && that.mainElem && options.target.find(that.mainElem.get(0)).length) that.render(type);
|
||
|
||
// 事件
|
||
that.events();
|
||
};
|
||
|
||
// 渲染
|
||
Class.prototype.render = function (type) {
|
||
var that = this;
|
||
var options = that.config;
|
||
var customName = options.customName;
|
||
|
||
// 默认菜单内容
|
||
var getDefaultView = function () {
|
||
var elemUl = $('<ul class="layui-menu layui-dropdown-menu"></ul>');
|
||
if (options.data.length > 0) {
|
||
eachItemView(elemUl, options.data);
|
||
} else {
|
||
elemUl.html('<li class="layui-menu-item-none">' + i18n.$t('dropdown.noData') + '</li>');
|
||
}
|
||
return elemUl;
|
||
};
|
||
|
||
// 遍历菜单项
|
||
var eachItemView = function (views, data) {
|
||
// var views = [];
|
||
|
||
layui.each(data, function (index, item) {
|
||
// 是否存在子级
|
||
var isChild = item[customName.children] && item[customName.children].length > 0;
|
||
var isSpreadItem = 'isSpreadItem' in item ? item.isSpreadItem : options.isSpreadItem;
|
||
var title = function (title) {
|
||
var templet = item.templet || options.templet;
|
||
if (templet) {
|
||
title = typeof templet === 'function' ? templet(item) : laytpl(templet).render(item);
|
||
}
|
||
return title;
|
||
}(util.escape(item[customName.title]));
|
||
|
||
// 初始类型
|
||
var type = function () {
|
||
if (isChild) {
|
||
item.type = item.type || 'parent';
|
||
}
|
||
if (item.type) {
|
||
return {
|
||
group: 'group',
|
||
parent: 'parent',
|
||
'-': '-'
|
||
}[item.type] || 'parent';
|
||
}
|
||
return '';
|
||
}();
|
||
if (type !== '-' && !item[customName.title] && !item[customName.id] && !isChild) return;
|
||
|
||
//列表元素
|
||
var viewLi = $(['<li' + function () {
|
||
var className = {
|
||
group: 'layui-menu-item-group' + (options.isAllowSpread ? isSpreadItem ? ' layui-menu-item-down' : ' layui-menu-item-up' : ''),
|
||
parent: STR_ITEM_PARENT,
|
||
'-': 'layui-menu-item-divider'
|
||
};
|
||
if (isChild || type) {
|
||
return ' class="' + className[type] + '"';
|
||
}
|
||
return item.disabled ? ' class="' + STR_DISABLED + '"' : '';
|
||
}() + '>',
|
||
//标题区
|
||
function () {
|
||
//是否超文本
|
||
var viewText = 'href' in item ? '<a href="' + item.href + '" target="' + (item.target || '_self') + '">' + title + '</a>' : title;
|
||
|
||
//是否存在子级
|
||
if (isChild) {
|
||
return '<div class="' + STR_MENU_TITLE + '">' + viewText + function () {
|
||
if (type === 'parent') {
|
||
return '<i class="layui-icon layui-icon-right"></i>';
|
||
} else if (type === 'group' && options.isAllowSpread) {
|
||
return '<i class="layui-icon layui-icon-' + (isSpreadItem ? 'up' : 'down') + '"></i>';
|
||
} else {
|
||
return '';
|
||
}
|
||
}() + '</div>';
|
||
}
|
||
return '<div class="' + STR_MENU_TITLE + '">' + viewText + '</div>';
|
||
}(), '</li>'].join(''));
|
||
viewLi.data('item', item);
|
||
|
||
//子级区
|
||
if (isChild) {
|
||
var elemPanel = $('<div class="layui-panel layui-menu-body-panel"></div>');
|
||
var elemUl = $('<ul></ul>');
|
||
if (type === 'parent') {
|
||
elemPanel.append(eachItemView(elemUl, item[customName.children]));
|
||
viewLi.append(elemPanel);
|
||
} else {
|
||
viewLi.append(eachItemView(elemUl, item[customName.children]));
|
||
}
|
||
}
|
||
views.append(viewLi);
|
||
});
|
||
return views;
|
||
};
|
||
|
||
// 主模板
|
||
var TPL_MAIN = ['<div class="layui-dropdown layui-border-box layui-panel layui-anim layui-anim-downbit" ' + MOD_ID + '="' + options.id + '">', '</div>'].join('');
|
||
|
||
// 重载或插入面板内容
|
||
var mainElem;
|
||
var content = options.content || getDefaultView();
|
||
var mainElemExisted = thisModule.findMainElem(options.id);
|
||
if (type === 'reloadData' && mainElemExisted.length) {
|
||
// 是否仅重载数据
|
||
mainElem = that.mainElem = mainElemExisted;
|
||
mainElemExisted.html(content);
|
||
} else {
|
||
// 常规渲染
|
||
mainElem = that.mainElem = $(TPL_MAIN);
|
||
mainElem.append(content);
|
||
|
||
// 初始化某些属性
|
||
mainElem.addClass(options.className);
|
||
mainElem.attr('style', options.style);
|
||
|
||
// 辞旧迎新
|
||
that.remove(options.id);
|
||
options.target.append(mainElem);
|
||
options.elem.data(MOD_INDEX_OPENED, true); // 面板已打开的标记
|
||
|
||
// 遮罩
|
||
var shade = options.shade ? '<div class="' + STR_ELEM_SHADE + '" style="' + ('z-index:' + (mainElem.css('z-index') - 1) + '; background-color: ' + (options.shade[1] || '#000') + '; opacity: ' + (options.shade[0] || options.shade)) + '"></div>' : '';
|
||
var shadeElem = $(shade);
|
||
// 处理移动端点击穿透问题
|
||
if (clickOrMousedown === 'touchstart') {
|
||
shadeElem.on(clickOrMousedown, function (e) {
|
||
e.preventDefault();
|
||
});
|
||
}
|
||
mainElem.before(shadeElem);
|
||
|
||
// 如果是鼠标移入事件,则鼠标移出时自动关闭
|
||
if (options.trigger === 'mouseenter') {
|
||
mainElem.on('mouseenter', function () {
|
||
clearTimeout(that.timer);
|
||
}).on('mouseleave', function () {
|
||
that.delayRemove();
|
||
});
|
||
}
|
||
}
|
||
that.position(); // 定位坐标
|
||
|
||
// 阻止全局事件
|
||
mainElem.find('.layui-menu').on(clickOrMousedown, function (e) {
|
||
layui.stope(e);
|
||
});
|
||
|
||
// 触发菜单列表事件
|
||
mainElem.find('.layui-menu li').on('click', function (e) {
|
||
var othis = $(this);
|
||
var data = othis.data('item') || {};
|
||
var isChild = data[customName.children] && data[customName.children].length > 0;
|
||
var isClickAllScope = options.clickScope === 'all'; // 是否所有父子菜单均触发点击事件
|
||
|
||
if (data.disabled) return; // 菜单项禁用状态
|
||
|
||
// 普通菜单项点击后的回调及关闭面板
|
||
if ((!isChild || isClickAllScope) && data.type !== '-') {
|
||
var ret = typeof options.click === 'function' ? options.click(data, othis, e) : null;
|
||
ret === false || isChild || that.remove();
|
||
layui.stope(e);
|
||
}
|
||
});
|
||
|
||
// 触发菜单组展开收缩
|
||
mainElem.find(STR_GROUP_TITLE).on('click', function (e) {
|
||
var othis = $(this);
|
||
var elemGroup = othis.parent();
|
||
var data = elemGroup.data('item') || {};
|
||
if (data.type === 'group' && options.isAllowSpread) {
|
||
thisModule.spread(elemGroup, options.accordion);
|
||
}
|
||
});
|
||
that.onClickOutside();
|
||
that.autoUpdatePosition();
|
||
|
||
// 组件打开完毕的事件
|
||
typeof options.ready === 'function' && options.ready(mainElem, options.elem);
|
||
};
|
||
|
||
// 位置定位
|
||
Class.prototype.position = function (obj) {
|
||
var that = this;
|
||
var options = that.config;
|
||
lay.position(options.elem[0], that.mainElem[0], {
|
||
position: options.position,
|
||
e: that.e,
|
||
clickType: options.trigger === 'contextmenu' ? 'right' : null,
|
||
align: options.align || null
|
||
});
|
||
};
|
||
|
||
// 移除面板
|
||
Class.prototype.remove = function (id) {
|
||
id = id || this.config.id;
|
||
var that = thisModule.getThis(id); // 根据 id 查找对应的实例
|
||
if (!that) return;
|
||
var options = that.config;
|
||
var mainElem = thisModule.findMainElem(id);
|
||
that.stopClickOutsideEvent();
|
||
that.stopResizeEvent();
|
||
|
||
// 若存在已打开的面板元素,则移除
|
||
if (mainElem[0]) {
|
||
mainElem.prev('.' + STR_ELEM_SHADE).remove(); // 先移除遮罩
|
||
mainElem.remove();
|
||
options.elem.removeData(MOD_INDEX_OPENED);
|
||
typeof options.close === 'function' && options.close(options.elem);
|
||
}
|
||
};
|
||
Class.prototype.normalizedDelay = function () {
|
||
var that = this;
|
||
var options = that.config;
|
||
var delay = [].concat(options.delay);
|
||
return {
|
||
show: delay[0],
|
||
hide: delay[1] !== undefined ? delay[1] : delay[0]
|
||
};
|
||
};
|
||
|
||
// 延迟移除面板
|
||
Class.prototype.delayRemove = function () {
|
||
var that = this;
|
||
that.config;
|
||
clearTimeout(that.timer);
|
||
that.timer = setTimeout(function () {
|
||
that.remove();
|
||
}, that.normalizedDelay().hide);
|
||
};
|
||
|
||
// 事件
|
||
Class.prototype.events = function () {
|
||
var that = this;
|
||
var options = that.config;
|
||
|
||
// 是否鼠标移入时触发
|
||
var isMouseEnter = options.trigger === 'mouseenter';
|
||
var trigger = options.trigger + '.lay_dropdown_render';
|
||
|
||
// 始终先解除上一个触发元素的事件(如重载时改变 elem 的情况)
|
||
if (that.thisEventElem) that.thisEventElem.off(trigger);
|
||
that.thisEventElem = options.elem;
|
||
|
||
// 触发元素事件
|
||
options.elem.off(trigger).on(trigger, function (e) {
|
||
clearTimeout(that.timer);
|
||
that.e = e;
|
||
|
||
// 主面板是否已打开
|
||
var opened = options.elem.data(MOD_INDEX_OPENED);
|
||
|
||
// 若为鼠标移入事件,则延迟触发
|
||
if (isMouseEnter) {
|
||
if (!opened) {
|
||
that.timer = setTimeout(function () {
|
||
that.render();
|
||
}, that.normalizedDelay().show);
|
||
}
|
||
} else {
|
||
// 若为 click 事件,则根据主面板状态,自动切换打开与关闭
|
||
if (options.closeOnClick && opened && options.trigger === 'click') {
|
||
that.remove();
|
||
} else {
|
||
that.render();
|
||
}
|
||
}
|
||
e.preventDefault();
|
||
});
|
||
|
||
// 如果是鼠标移入事件
|
||
if (isMouseEnter) {
|
||
// 执行鼠标移出事件
|
||
options.elem.on('mouseleave', function () {
|
||
that.delayRemove();
|
||
});
|
||
}
|
||
};
|
||
|
||
/**
|
||
* 点击面板外部时的事件
|
||
*/
|
||
Class.prototype.onClickOutside = function () {
|
||
var that = this;
|
||
var options = that.config;
|
||
var isCtxMenu = options.trigger === 'contextmenu';
|
||
var isTopElem = lay.isTopElem(options.elem[0]);
|
||
that.stopClickOutsideEvent();
|
||
var stop = lay.onClickOutside(that.mainElem[0], function (e) {
|
||
// 点击面板外部时的事件
|
||
if (typeof options.onClickOutside === 'function') {
|
||
var shouldClose = options.onClickOutside(e);
|
||
if (shouldClose === false) return;
|
||
}
|
||
that.remove();
|
||
}, {
|
||
ignore: isCtxMenu || isTopElem ? null : [options.elem[0]],
|
||
event: clickOrMousedown,
|
||
capture: false,
|
||
detectIframe: true
|
||
});
|
||
that.stopClickOutsideEvent = function () {
|
||
stop();
|
||
that.stopClickOutsideEvent = $.noop;
|
||
};
|
||
};
|
||
|
||
/**
|
||
* 窗口大小变化时自动更新位置
|
||
*/
|
||
Class.prototype.autoUpdatePosition = function () {
|
||
var that = this;
|
||
var options = that.config;
|
||
that.stopResizeEvent();
|
||
var windowResizeHandler = function () {
|
||
if (that.mainElem && (!that.mainElem[0] || !that.mainElem.is(':visible'))) return;
|
||
if (options.trigger === 'contextmenu') {
|
||
that.remove();
|
||
} else {
|
||
that.position();
|
||
}
|
||
};
|
||
$(window).on('resize.lay_dropdown_resize', windowResizeHandler);
|
||
var shouldObserveResize = resizeObserver && options.trigger !== 'contextmenu';
|
||
var triggerEl = options.elem[0];
|
||
var contentEl = that.mainElem[0];
|
||
if (shouldObserveResize) {
|
||
resizeObserver.observe(triggerEl, $.proxy(that.position, that));
|
||
resizeObserver.observe(contentEl, $.proxy(that.position, that));
|
||
}
|
||
that.stopResizeEvent = function () {
|
||
$(window).off('resize.lay_dropdown_resize', windowResizeHandler);
|
||
if (shouldObserveResize) {
|
||
resizeObserver.unobserve(triggerEl);
|
||
resizeObserver.unobserve(contentEl);
|
||
}
|
||
that.stopResizeEvent = $.noop;
|
||
};
|
||
};
|
||
|
||
// 记录所有实例
|
||
thisModule.that = {}; // 记录所有实例对象
|
||
|
||
// 获取当前实例对象
|
||
thisModule.getThis = function (id) {
|
||
if (id === undefined) {
|
||
throw new Error('ID argument required');
|
||
}
|
||
return thisModule.that[id];
|
||
};
|
||
|
||
// 根据 id 从页面查找组件主面板元素
|
||
thisModule.findMainElem = function (id) {
|
||
return $('.' + STR_ELEM + '[' + MOD_ID + '="' + id + '"]');
|
||
};
|
||
|
||
// 设置菜单组展开和收缩状态
|
||
thisModule.spread = function (othis, isAccordion) {
|
||
var contentElem = othis.children('ul');
|
||
var needSpread = othis.hasClass(STR_ITEM_UP);
|
||
var ANIM_MS = 200;
|
||
|
||
// 动画执行完成后的操作
|
||
var complete = function () {
|
||
$(this).css({
|
||
display: ''
|
||
}); // 剔除临时 style,以适配外部样式的状态重置;
|
||
};
|
||
|
||
// 动画是否正在执行
|
||
if (contentElem.is(':animated')) return;
|
||
|
||
// 展开
|
||
if (needSpread) {
|
||
othis.removeClass(STR_ITEM_UP).addClass(STR_ITEM_DOWN);
|
||
contentElem.hide().stop().slideDown(ANIM_MS, complete);
|
||
} else {
|
||
// 收缩
|
||
contentElem.stop().slideUp(ANIM_MS, complete);
|
||
othis.removeClass(STR_ITEM_DOWN).addClass(STR_ITEM_UP);
|
||
}
|
||
|
||
// 手风琴
|
||
if (needSpread && isAccordion) {
|
||
var groupSibs = othis.siblings('.' + STR_ITEM_DOWN);
|
||
groupSibs.children('ul').stop().slideUp(ANIM_MS, complete);
|
||
groupSibs.removeClass(STR_ITEM_DOWN).addClass(STR_ITEM_UP);
|
||
}
|
||
};
|
||
|
||
// 全局事件
|
||
(function () {
|
||
var _WIN = $(window);
|
||
var _DOC = $(document);
|
||
|
||
// 基础菜单的静态元素事件
|
||
var ELEM_LI = '.layui-menu:not(.layui-dropdown-menu) li';
|
||
_DOC.on('click', ELEM_LI, function (e) {
|
||
var othis = $(this);
|
||
var parent = othis.parents('.layui-menu').eq(0);
|
||
var isChild = othis.hasClass(STR_ITEM_GROUP) || othis.hasClass(STR_ITEM_PARENT);
|
||
var filter = parent.attr('lay-filter') || parent.attr('id');
|
||
var options = lay.options(this);
|
||
|
||
// 非触发元素
|
||
if (othis.hasClass(STR_ITEM_DIV)) return;
|
||
|
||
// 非菜单组
|
||
if (!isChild) {
|
||
// 选中
|
||
parent.find('.' + STR_ITEM_CHECKED).removeClass(STR_ITEM_CHECKED); // 清除选中样式
|
||
parent.find('.' + STR_ITEM_CHECKED2).removeClass(STR_ITEM_CHECKED2); // 清除父级菜单选中样式
|
||
othis.addClass(STR_ITEM_CHECKED); //添加选中样式
|
||
othis.parents('.' + STR_ITEM_PARENT).addClass(STR_ITEM_CHECKED2); // 添加父级菜单选中样式
|
||
|
||
options.title = options.title || $.trim(othis.children('.' + STR_MENU_TITLE).text());
|
||
|
||
// 触发事件
|
||
layui.event.call(this, MOD_NAME, 'click(' + filter + ')', options);
|
||
}
|
||
});
|
||
|
||
// 基础菜单的展开收缩事件
|
||
_DOC.on('click', ELEM_LI + STR_GROUP_TITLE, function (e) {
|
||
var othis = $(this);
|
||
var elemGroup = othis.parents('.' + STR_ITEM_GROUP + ':eq(0)');
|
||
var options = lay.options(elemGroup[0]);
|
||
var isAccordion = typeof othis.parents('.layui-menu').eq(0).attr('lay-accordion') === 'string';
|
||
if ('isAllowSpread' in options ? options.isAllowSpread : true) {
|
||
thisModule.spread(elemGroup, isAccordion);
|
||
}
|
||
});
|
||
|
||
// 判断子级菜单是否超出屏幕
|
||
var ELEM_LI_PAR = '.layui-menu .' + STR_ITEM_PARENT;
|
||
_DOC.on('mouseenter', ELEM_LI_PAR, function (e) {
|
||
var othis = $(this);
|
||
var elemPanel = othis.find('.' + STR_MENU_PANEL);
|
||
if (!elemPanel[0]) return;
|
||
var rect = elemPanel[0].getBoundingClientRect();
|
||
|
||
// 是否超出右侧屏幕
|
||
if (rect.right > _WIN.width()) {
|
||
elemPanel.addClass(STR_MENU_PANEL_L);
|
||
// 不允许超出左侧屏幕
|
||
rect = elemPanel[0].getBoundingClientRect();
|
||
if (rect.left < 0) {
|
||
elemPanel.removeClass(STR_MENU_PANEL_L);
|
||
}
|
||
}
|
||
|
||
// 是否超出底部屏幕
|
||
if (rect.bottom > _WIN.height()) {
|
||
elemPanel.eq(0).css('margin-top', -(rect.bottom - _WIN.height() + 5));
|
||
}
|
||
}).on('mouseleave', ELEM_LI_PAR, function (e) {
|
||
var othis = $(this);
|
||
var elemPanel = othis.children('.' + STR_MENU_PANEL);
|
||
elemPanel.removeClass(STR_MENU_PANEL_L);
|
||
elemPanel.css('margin-top', 0);
|
||
});
|
||
})();
|
||
|
||
// 关闭面板
|
||
dropdown.close = function (id) {
|
||
var that = thisModule.getThis(id);
|
||
if (!that) return this;
|
||
that.remove();
|
||
return thisModule.call(that);
|
||
};
|
||
|
||
// 打开面板
|
||
dropdown.open = function (id) {
|
||
var that = thisModule.getThis(id);
|
||
if (!that) return this;
|
||
that.render();
|
||
return thisModule.call(that);
|
||
};
|
||
|
||
// 重载实例
|
||
dropdown.reload = function (id, options, type) {
|
||
var that = thisModule.getThis(id);
|
||
if (!that) return this;
|
||
that.reload(options, type);
|
||
return thisModule.call(that);
|
||
};
|
||
|
||
// 仅重载数据
|
||
dropdown.reloadData = function () {
|
||
var args = $.extend([], arguments);
|
||
args[2] = 'reloadData';
|
||
|
||
// 重载时,与数据相关的参数
|
||
var dataParams = new RegExp('^(' + ['data', 'templet', 'content'].join('|') + ')$');
|
||
|
||
// 过滤与数据无关的参数
|
||
layui.each(args[1], function (key, value) {
|
||
if (!dataParams.test(key)) {
|
||
delete args[1][key];
|
||
}
|
||
});
|
||
return dropdown.reload.apply(null, args);
|
||
};
|
||
|
||
// 核心入口
|
||
dropdown.render = function (options) {
|
||
var inst = new Class(options);
|
||
return thisModule.call(inst);
|
||
};
|
||
|
||
export { dropdown };
|