mirror of https://github.com/layui/layui
feat(dropdown): 支持同时打开多个
parent
3c64d33e6e
commit
e731de490c
|
@ -95,6 +95,8 @@ layui.define(['i18n', 'jquery', 'laytpl', 'lay', 'util'], function(exports) {
|
|||
var that = this;
|
||||
that.index = ++dropdown.index;
|
||||
that.config = $.extend({}, that.config, dropdown.config, options);
|
||||
that.stopClickOutsideEvent = $.noop;
|
||||
that.stopResizeEvent = $.noop;
|
||||
that.init();
|
||||
};
|
||||
|
||||
|
@ -307,18 +309,25 @@ layui.define(['i18n', 'jquery', 'laytpl', 'lay', 'util'], function(exports) {
|
|||
mainElem.attr('style', options.style);
|
||||
|
||||
// 辞旧迎新
|
||||
that.remove(dropdown.thisId);
|
||||
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>') : '';
|
||||
mainElem.before(shade);
|
||||
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(thisModule.timer);
|
||||
clearTimeout(that.timer);
|
||||
}).on('mouseleave', function(){
|
||||
that.delayRemove();
|
||||
});
|
||||
|
@ -326,7 +335,6 @@ layui.define(['i18n', 'jquery', 'laytpl', 'lay', 'util'], function(exports) {
|
|||
}
|
||||
|
||||
that.position(); // 定位坐标
|
||||
dropdown.thisId = options.id; // 当前打开的面板 id
|
||||
|
||||
// 阻止全局事件
|
||||
mainElem.find('.layui-menu').on(clickOrMousedown, function(e){
|
||||
|
@ -369,6 +377,11 @@ layui.define(['i18n', 'jquery', 'laytpl', 'lay', 'util'], function(exports) {
|
|||
resizeObserver.observe(mainElem[0], that.position.bind(that));
|
||||
}
|
||||
|
||||
that.stopClickOutsideEvent();
|
||||
that.stopResizeEvent();
|
||||
that.stopClickOutsideEvent = that.onClickOutside();
|
||||
that.stopResizeEvent = that.autoUpdatePosition();
|
||||
|
||||
// 组件打开完毕的事件
|
||||
typeof options.ready === 'function' && options.ready(mainElem, options.elem);
|
||||
};
|
||||
|
@ -410,6 +423,12 @@ layui.define(['i18n', 'jquery', 'laytpl', 'lay', 'util'], function(exports) {
|
|||
delete dropdown.thisId;
|
||||
typeof options.close === 'function' && options.close(options.elem);
|
||||
}
|
||||
|
||||
// 关闭后移除全局事件
|
||||
that.stopResizeEvent();
|
||||
that.stopResizeEvent = $.noop;
|
||||
that.stopClickOutsideEvent();
|
||||
that.stopClickOutsideEvent = $.noop;
|
||||
};
|
||||
|
||||
Class.prototype.normalizedDelay = function(){
|
||||
|
@ -427,9 +446,9 @@ layui.define(['i18n', 'jquery', 'laytpl', 'lay', 'util'], function(exports) {
|
|||
Class.prototype.delayRemove = function(){
|
||||
var that = this;
|
||||
var options = that.config;
|
||||
clearTimeout(thisModule.timer);
|
||||
clearTimeout(that.timer);
|
||||
|
||||
thisModule.timer = setTimeout(function(){
|
||||
that.timer = setTimeout(function(){
|
||||
that.remove();
|
||||
}, that.normalizedDelay().hide);
|
||||
};
|
||||
|
@ -449,7 +468,7 @@ layui.define(['i18n', 'jquery', 'laytpl', 'lay', 'util'], function(exports) {
|
|||
|
||||
// 触发元素事件
|
||||
options.elem.off(trigger).on(trigger, function(e) {
|
||||
clearTimeout(thisModule.timer);
|
||||
clearTimeout(that.timer);
|
||||
that.e = e;
|
||||
|
||||
// 主面板是否已打开
|
||||
|
@ -458,7 +477,7 @@ layui.define(['i18n', 'jquery', 'laytpl', 'lay', 'util'], function(exports) {
|
|||
// 若为鼠标移入事件,则延迟触发
|
||||
if (isMouseEnter) {
|
||||
if (!opened) {
|
||||
thisModule.timer = setTimeout(function(){
|
||||
that.timer = setTimeout(function(){
|
||||
that.render();
|
||||
}, that.normalizedDelay().show);
|
||||
}
|
||||
|
@ -483,6 +502,60 @@ layui.define(['i18n', 'jquery', 'laytpl', 'lay', 'util'], function(exports) {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 点击面板外部时的事件
|
||||
* @returns {() => void} 返回一个函数,用于取消事件
|
||||
*/
|
||||
Class.prototype.onClickOutside = function () {
|
||||
var that = this;
|
||||
var options = that.config;
|
||||
var isCtxMenu = options.trigger === 'contextmenu';
|
||||
var isTopElem = lay.isTopElem(options.elem[0]);
|
||||
|
||||
return 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
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* 窗口大小变化时自动更新位置
|
||||
* @returns {() => void} 返回一个函数,用于取消事件
|
||||
*/
|
||||
Class.prototype.autoUpdatePosition = function(){
|
||||
var that = this;
|
||||
var options = that.config;
|
||||
|
||||
var handleResize = 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', handleResize)
|
||||
|
||||
return function(){
|
||||
$(window).off('resize.lay_dropdown_resize')
|
||||
}
|
||||
}
|
||||
|
||||
// 记录所有实例
|
||||
thisModule.that = {}; // 记录所有实例对象
|
||||
|
||||
|
@ -535,78 +608,6 @@ layui.define(['i18n', 'jquery', 'laytpl', 'lay', 'util'], function(exports) {
|
|||
var _WIN = $(window);
|
||||
var _DOC = $(document);
|
||||
|
||||
// 自适应定位
|
||||
_WIN.on('resize', function(){
|
||||
if(!dropdown.thisId) return;
|
||||
var that = thisModule.getThis(dropdown.thisId);
|
||||
if(!that) return;
|
||||
|
||||
if((that.mainElem && !that.mainElem[0]) || !$('.'+ STR_ELEM)[0]){
|
||||
return false;
|
||||
}
|
||||
|
||||
var options = that.config;
|
||||
|
||||
if(options.trigger === 'contextmenu'){
|
||||
that.remove();
|
||||
} else {
|
||||
that.position();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
// 点击任意处关闭
|
||||
lay(_DOC).on(clickOrMousedown, function(e){
|
||||
if(!dropdown.thisId) return;
|
||||
var that = thisModule.getThis(dropdown.thisId)
|
||||
if(!that) return;
|
||||
|
||||
var options = that.config;
|
||||
var isTopElem = lay.isTopElem(options.elem[0]);
|
||||
var isCtxMenu = options.trigger === 'contextmenu';
|
||||
|
||||
// 若触发的是绑定的元素,或者属于绑定元素的子元素,则不关闭
|
||||
// 满足条件:当前绑定的元素是 body document,或者是鼠标右键事件时,忽略绑定元素
|
||||
var isTriggerTarget = !(isTopElem || isCtxMenu) && (options.elem[0] === e.target || options.elem.find(e.target)[0]);
|
||||
var isPanelTarget = that.mainElem && (e.target === that.mainElem[0] || that.mainElem.find(e.target)[0]);
|
||||
if(isTriggerTarget || isPanelTarget) return;
|
||||
// 处理移动端点击穿透问题
|
||||
if(e.type === 'touchstart' && options.elem.data(MOD_INDEX_OPENED)){
|
||||
$(e.target).hasClass(STR_ELEM_SHADE) && e.preventDefault();
|
||||
}
|
||||
|
||||
// 点击 dropdown 外部时的回调
|
||||
if(typeof options.onClickOutside === 'function'){
|
||||
var shouldClose = options.onClickOutside(e);
|
||||
if(shouldClose === false) return;
|
||||
}
|
||||
|
||||
that.remove();
|
||||
}, lay.passiveSupported ? { passive: false} : false);
|
||||
|
||||
// onClickOutside 检测 iframe
|
||||
_WIN.on('blur', function(e){
|
||||
if(!dropdown.thisId) return;
|
||||
var that = thisModule.getThis(dropdown.thisId)
|
||||
if(!that) return;
|
||||
if(!that.config.elem.data(MOD_INDEX_OPENED)) return;
|
||||
|
||||
setTimeout(function(){
|
||||
if(document.activeElement && document.activeElement.tagName === 'IFRAME'
|
||||
&& that.mainElem && that.mainElem[0]
|
||||
&& that.mainElem[0].contains && !that.mainElem[0].contains(document.activeElement)
|
||||
){
|
||||
// 点击 dropdown 外部时的回调
|
||||
if(typeof that.config.onClickOutside === 'function'){
|
||||
var shouldClose = that.config.onClickOutside(e.originalEvent);
|
||||
if(shouldClose === false) return;
|
||||
}
|
||||
that.remove();
|
||||
}
|
||||
}, 0);
|
||||
})
|
||||
|
||||
// 基础菜单的静态元素事件
|
||||
var ELEM_LI = '.layui-menu:not(.layui-dropdown-menu) li';
|
||||
_DOC.on('click', ELEM_LI, function(e){
|
||||
|
|
Loading…
Reference in New Issue