From c323af0d8a0d0b050ee9d23f5be162be52f25f4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B4=A4=E5=BF=83?= <3277200+sentsim@users.noreply.github.com> Date: Tue, 11 Jul 2023 15:20:08 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=20dropdown=20=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E4=B9=A6=E5=86=99=E8=A7=84=E8=8C=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/modules/dropdown.js | 267 +++++++++++++++++++++------------------- 1 file changed, 140 insertions(+), 127 deletions(-) diff --git a/src/modules/dropdown.js b/src/modules/dropdown.js index 6c2d4e3b..3fff8352 100644 --- a/src/modules/dropdown.js +++ b/src/modules/dropdown.js @@ -6,86 +6,99 @@ layui.define(['jquery', 'laytpl', 'lay'], function(exports){ "use strict"; - var $ = layui.$ - ,laytpl = layui.laytpl - ,hint = layui.hint() - ,device = layui.device() - ,clickOrMousedown = (device.mobile ? 'touchstart' : 'mousedown') + var $ = layui.$; + var laytpl = layui.laytpl; + var hint = layui.hint(); + var device = layui.device(); + var clickOrMousedown = (device.mobile ? 'touchstart' : 'mousedown'); - //模块名 - ,MOD_NAME = 'dropdown' - ,MOD_INDEX = 'layui_'+ MOD_NAME +'_index' //模块索引名 + // 模块名 + var MOD_NAME = 'dropdown'; + var MOD_INDEX = 'layui_'+ MOD_NAME +'_index'; // 模块索引名 - //外部接口 - ,dropdown = { - config: {} - ,index: layui[MOD_NAME] ? (layui[MOD_NAME].index + 10000) : 0 + // 外部接口 + var dropdown = { + config: {}, + index: layui[MOD_NAME] ? (layui[MOD_NAME].index + 10000) : 0, - //设置全局项 - ,set: function(options){ + // 设置全局项 + set: function(options){ var that = this; that.config = $.extend({}, that.config, options); return that; - } + }, - //事件 - ,on: function(events, callback){ + // 事件 + on: function(events, callback){ return layui.onevent.call(this, MOD_NAME, events, callback); } - } + }; - //操作当前实例 - ,thisModule = function(){ + // 操作当前实例 + var thisModule = function(){ var that = this; var options = that.config; var id = options.id; - thisModule.that[id] = that; //记录当前实例对象 + thisModule.that[id] = that; // 记录当前实例对象 return { - config: options - //重置实例 - ,reload: function(options){ + config: options, + // 重置实例 + reload: function(options){ that.reload.call(that, options); - } - ,reloadData: function(options){ + }, + reloadData: function(options){ dropdown.reloadData(id, options); - } - ,close: function () { + }, + close: function () { that.remove() } } - } + }; - //字符常量 - ,STR_ELEM = 'layui-dropdown', STR_HIDE = 'layui-hide', STR_DISABLED = 'layui-disabled', STR_NONE = 'layui-none' - ,STR_ITEM_UP = 'layui-menu-item-up', STR_ITEM_DOWN = 'layui-menu-item-down', STR_MENU_TITLE = 'layui-menu-body-title', STR_ITEM_GROUP = 'layui-menu-item-group', STR_ITEM_PARENT = 'layui-menu-item-parent', STR_ITEM_DIV = 'layui-menu-item-divider', STR_ITEM_CHECKED = 'layui-menu-item-checked', STR_ITEM_CHECKED2 = 'layui-menu-item-checked2', STR_MENU_PANEL = 'layui-menu-body-panel', STR_MENU_PANEL_L = 'layui-menu-body-panel-left', STR_ELEM_SHADE = 'layui-dropdown-shade' + // 字符常量 + var STR_ELEM = 'layui-dropdown'; + var STR_HIDE = 'layui-hide'; + var STR_DISABLED = 'layui-disabled'; + var STR_NONE = 'layui-none'; + 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'; - ,STR_GROUP_TITLE = '.'+ STR_ITEM_GROUP + '>.'+ STR_MENU_TITLE + var STR_GROUP_TITLE = '.'+ STR_ITEM_GROUP + '>.'+ STR_MENU_TITLE; - //构造器 - ,Class = function(options){ + // 构造器 + var Class = function(options){ var that = this; that.index = ++dropdown.index; that.config = $.extend({}, that.config, dropdown.config, options); that.init(); }; - //默认配置 + // 默认配置 Class.prototype.config = { - trigger: 'click' //事件类型 - ,content: '' //自定义菜单内容 - ,className: '' //自定义样式类名 - ,style: '' //设置面板 style 属性 - ,show: false //是否初始即显示菜单面板 - ,isAllowSpread: true //是否允许菜单组展开收缩 - ,isSpreadItem: true //是否初始展开子菜单 - ,data: [] //菜单数据结构 - ,delay: 300 //延迟关闭的毫秒数,若 trigger 为 hover 时才生效 - ,shade: 0 // 遮罩 + trigger: 'click', // 事件类型 + content: '', // 自定义菜单内容 + className: '', // 自定义样式类名 + style: '', // 设置面板 style 属性 + show: false, // 是否初始即显示菜单面板 + isAllowSpread: true, // 是否允许菜单组展开收缩 + isSpreadItem: true, // 是否初始展开子菜单 + data: [], // 菜单数据结构 + delay: 300, // 延迟关闭的毫秒数,若 trigger 为 hover 时才生效 + shade: 0 // 遮罩 }; - //重载实例 + // 重载实例 Class.prototype.reload = function(options, type){ var that = this; that.config = $.extend({}, that.config, options); @@ -240,19 +253,19 @@ layui.define(['jquery', 'laytpl', 'lay'], function(exports){ views.append(viewLi); }); return views; - } + }; - //主模板 - ,TPL_MAIN = ['
' + // 主模板 + var TPL_MAIN = ['
' ,'
'].join(''); - //如果是右键事件,则每次触发事件时,将允许重新渲染 + // 如果是右键事件,则每次触发事件时,将允许重新渲染 if(options.trigger === 'contextmenu' || lay.isTopElem(options.elem[0])) rerender = true; - //判断是否已经打开了下拉菜单面板 + // 判断是否已经打开了下拉菜单面板 if(!rerender && options.elem.data(MOD_INDEX +'_opened')) return; - //记录模板对象 + // 记录模板对象 that.elemView = $('.' + STR_ELEM + '[lay-id="' + options.id + '"]'); if (type === 'reloadData' && that.elemView.length) { that.elemView.html(options.content || getDefaultView()); @@ -260,23 +273,23 @@ layui.define(['jquery', 'laytpl', 'lay'], function(exports){ that.elemView = $(TPL_MAIN); that.elemView.append(options.content || getDefaultView()); - //初始化某些属性 + // 初始化某些属性 if(options.className) that.elemView.addClass(options.className); if(options.style) that.elemView.attr('style', options.style); - //记录当前执行的实例索引 + // 记录当前执行的实例索引 dropdown.thisId = options.id; - //插入视图 - that.remove(); //移除非当前绑定元素的面板 + // 插入视图 + that.remove(); // 移除非当前绑定元素的面板 elemBody.append(that.elemView); options.elem.data(MOD_INDEX +'_opened', true); - //遮罩 + // 遮罩 var shade = options.shade ? ('
') : ''; that.elemView.before(shade); - //如果是鼠标移入事件,则鼠标移出时自动关闭 + // 如果是鼠标移入事件,则鼠标移出时自动关闭 if(options.trigger === 'mouseenter'){ that.elemView.on('mouseenter', function(){ clearTimeout(thisModule.timer); @@ -286,17 +299,17 @@ layui.define(['jquery', 'laytpl', 'lay'], function(exports){ } } - //坐标定位 + // 坐标定位 that.position(); - thisModule.prevElem = that.elemView; //记录当前打开的元素,以便在下次关闭 - thisModule.prevElem.data('prevElem', options.elem); //将当前绑定的元素,记录在打开元素的 data 对象中 + thisModule.prevElem = that.elemView; // 记录当前打开的元素,以便在下次关闭 + thisModule.prevElem.data('prevElem', options.elem); // 将当前绑定的元素,记录在打开元素的 data 对象中 - //阻止全局事件 + // 阻止全局事件 that.elemView.find('.layui-menu').on(clickOrMousedown, function(e){ layui.stope(e); }); - //触发菜单列表事件 + // 触发菜单列表事件 that.elemView.find('.layui-menu li').on('click', function(e){ var othis = $(this); var data = othis.data('item') || {}; @@ -316,7 +329,7 @@ layui.define(['jquery', 'laytpl', 'lay'], function(exports){ } }); - //触发菜单组展开收缩 + // 触发菜单组展开收缩 that.elemView.find(STR_GROUP_TITLE).on('click', function(e){ var othis = $(this) ,elemGroup = othis.parent() @@ -334,26 +347,26 @@ layui.define(['jquery', 'laytpl', 'lay'], function(exports){ ); }; - //位置定位 + // 位置定位 Class.prototype.position = function(obj){ - var that = this - ,options = that.config; + var that = this; + var options = that.config; lay.position(options.elem[0], that.elemView[0], { - position: options.position - ,e: that.e - ,clickType: options.trigger === 'contextmenu' ? 'right' : null - ,align: options.align || null + position: options.position, + e: that.e, + clickType: options.trigger === 'contextmenu' ? 'right' : null, + align: options.align || null }); }; - //删除视图 + // 删除视图 Class.prototype.remove = function(){ - var that = this - ,options = that.config - ,elemPrev = thisModule.prevElem; + var that = this; + var options = that.config; + var elemPrev = thisModule.prevElem; - //若存在已打开的面板元素,则移除 + // 若存在已打开的面板元素,则移除 if(elemPrev){ elemPrev.data('prevElem') && ( elemPrev.data('prevElem').data(MOD_INDEX +'_opened', false) @@ -363,10 +376,10 @@ layui.define(['jquery', 'laytpl', 'lay'], function(exports){ lay('.' + STR_ELEM_SHADE).remove(); }; - //延迟删除视图 + // 延迟删除视图 Class.prototype.delayRemove = function(){ - var that = this - ,options = that.config; + var that = this; + var options = that.config; clearTimeout(thisModule.timer); thisModule.timer = setTimeout(function(){ @@ -374,18 +387,18 @@ layui.define(['jquery', 'laytpl', 'lay'], function(exports){ }, options.delay); }; - //事件 + // 事件 Class.prototype.events = function(){ - var that = this - ,options = that.config; + var that = this; + var options = that.config; - //如果传入 hover,则解析为 mouseenter + // 若传入 hover,则解析为 mouseenter if(options.trigger === 'hover') options.trigger = 'mouseenter'; - //解除上一个事件 + // 解除上一个事件 if(that.prevElem) that.prevElem.off(options.trigger, that.prevElemCallback); - //记录被绑定的元素及回调 + // 记录被绑定的元素及回调 that.prevElem = options.elem; that.prevElemCallback = function(e){ clearTimeout(thisModule.timer); @@ -394,31 +407,31 @@ layui.define(['jquery', 'laytpl', 'lay'], function(exports){ e.preventDefault(); }; - //触发元素事件 + // 触发元素事件 options.elem.on(options.trigger, that.prevElemCallback); - //如果是鼠标移入事件 + // 如果是鼠标移入事件 if(options.trigger === 'mouseenter'){ - //直行鼠标移出事件 + // 直行鼠标移出事件 options.elem.on('mouseleave', function(){ that.delayRemove(); }); } }; - //记录所有实例 - thisModule.that = {}; //记录所有实例对象 + // 记录所有实例 + thisModule.that = {}; // 记录所有实例对象 - //获取当前实例对象 + // 获取当前实例对象 thisModule.getThis = function(id){ var that = thisModule.that[id]; if(!that) hint.error(id ? (MOD_NAME +' instance with ID \''+ id +'\' not found') : 'ID argument required'); return that; }; - //设置菜单组展开和收缩状态 + // 设置菜单组展开和收缩状态 thisModule.spread = function(othis){ - //菜单组展开和收缩 + // 菜单组展开和收缩 var needSpread = othis.hasClass(STR_ITEM_UP); var elemIcon = othis.children('.'+ STR_MENU_TITLE).find('.layui-icon-' + (needSpread ? 'down' : 'up')); if(needSpread){ @@ -430,12 +443,12 @@ layui.define(['jquery', 'laytpl', 'lay'], function(exports){ } }; - //全局事件 - ;!function(){ - var _WIN = $(window) - ,_DOC = $(document); + // 全局事件 + (function(){ + var _WIN = $(window); + var _DOC = $(document); - //自适应定位 + // 自适应定位 _WIN.on('resize', function(){ if(!dropdown.thisId) return; var that = thisModule.getThis(dropdown.thisId); @@ -456,7 +469,7 @@ layui.define(['jquery', 'laytpl', 'lay'], function(exports){ - //点击任意处关闭 + // 点击任意处关闭 _DOC.on(clickOrMousedown, function(e){ if(!dropdown.thisId) return; var that = thisModule.getThis(dropdown.thisId) @@ -464,8 +477,8 @@ layui.define(['jquery', 'laytpl', 'lay'], function(exports){ var options = that.config; - //如果触发的是绑定的元素,或者属于绑定元素的子元素,则不关闭 - //满足条件:当前绑定的元素不是 body document,或者不是鼠标右键事件 + // 若触发的是绑定的元素,或者属于绑定元素的子元素,则不关闭 + // 满足条件:当前绑定的元素不是 body document,或者不是鼠标右键事件 if(!(lay.isTopElem(options.elem[0]) || options.trigger === 'contextmenu')){ if( e.target === options.elem[0] || @@ -478,76 +491,76 @@ layui.define(['jquery', 'laytpl', 'lay'], function(exports){ that.remove(); }); - //基础菜单的静态元素事件 + // 基础菜单的静态元素事件 var ELEM_LI = '.layui-menu:not(.layui-dropdown-menu) li'; _DOC.on('click', ELEM_LI, function(e){ - var othis = $(this) - ,parent = othis.parents('.layui-menu').eq(0) - ,isChild = othis.hasClass(STR_ITEM_GROUP) || othis.hasClass(STR_ITEM_PARENT) - ,filter = parent.attr('lay-filter') || parent.attr('id') - ,options = lay.options(this); + 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); //清除父级菜单选中样式 + // 选中 + 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); //添加父级菜单选中样式 + 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) - ,elemGroup = othis.parents('.'+ STR_ITEM_GROUP +':eq(0)') - ,options = lay.options(elemGroup[0]); + var othis = $(this); + var elemGroup = othis.parents('.'+ STR_ITEM_GROUP +':eq(0)'); + var options = lay.options(elemGroup[0]); if(('isAllowSpread' in options) ? options.isAllowSpread : true){ thisModule.spread(elemGroup); } }); - //判断子级菜单是否超出屏幕 + // 判断子级菜单是否超出屏幕 var ELEM_LI_PAR = '.layui-menu .'+ STR_ITEM_PARENT _DOC.on('mouseenter', ELEM_LI_PAR, function(e){ - var othis = $(this) - ,elemPanel = othis.find('.'+ STR_MENU_PANEL); + 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) - ,elemPanel = othis.children('.'+ STR_MENU_PANEL); + var elemPanel = othis.children('.'+ STR_MENU_PANEL); elemPanel.removeClass(STR_MENU_PANEL_L); elemPanel.css('margin-top', 0); }); - }(); + })(); // 关闭面板 dropdown.close = function(id){