/** * element * 常用元素操作组件 */ layui.define('jquery', function(exports){ 'use strict'; var $ = layui.$; var hint = layui.hint(); var device = layui.device(); var MOD_NAME = 'element'; var THIS = 'layui-this'; var SHOW = 'layui-show'; var TITLE = '.layui-tab-title'; var Element = function(){ this.config = {}; }; // 全局设置 Element.prototype.set = function(options){ var that = this; $.extend(true, that.config, options); return that; }; // 表单事件 Element.prototype.on = function(events, callback){ return layui.onevent.call(this, MOD_NAME, events, callback); }; // 外部 Tab 新增 Element.prototype.tabAdd = function(filter, options){ var tabElem = $('.layui-tab[lay-filter='+ filter +']'); var titElem = tabElem.children(TITLE); var barElem = titElem.children('.layui-tab-bar'); var contElem = tabElem.children('.layui-tab-content'); var li = ' 0) layAttr.unshift(''); //向前插,预留空格 return layAttr.join(' '); }() +'>'+ (options.title || 'unnaming') +''; barElem[0] ? barElem.before(li) : titElem.append(li); contElem.append('
'+ (options.content || '') +'
'); // call.hideTabMore(true); // 是否添加即切换 options.change && this.tabChange(filter, options.id); titElem.data('LAY_TAB_CHANGE', options.change); call.tabAuto(options.change ? 'change' : null, tabElem); return this; }; /** * 外部 Tab 删除 * @param {string} filter - 标签主容器 lay-filter 值 * @param {string} layid - 标签头 lay-id 值 * @param {boolean} force - 是否强制删除 * @returns {this} */ Element.prototype.tabDelete = function(filter, layid, force){ var tabElem = $('.layui-tab[lay-filter='+ filter +']'); var titElem = tabElem.children(TITLE); var liElem = titElem.find('>li[lay-id="'+ layid +'"]'); call.tabDelete.call(liElem[0], { liElem: liElem, force: force }); return this; }; /** * 外部 Tab 切换 * @param {string} filter - 标签主容器 lay-filter 值 * @param {string} layid - 标签头 lay-id 值 * @param {boolean} force - 是否强制切换 * @returns {this} */ Element.prototype.tabChange = function(filter, layid, force){ var tabElem = $('.layui-tab[lay-filter='+ filter +']'); var titElem = tabElem.children(TITLE); var liElem = titElem.find('>li[lay-id="'+ layid +'"]'); call.tabClick.call(liElem[0], { liElem: liElem, force: force }); return this; }; // 自定义 Tab 选项卡 Element.prototype.tab = function(options){ options = options || {}; dom.on('click', options.headerElem, function(e){ var index = $(options.headerElem).index($(this)); call.tabClick.call(this, { index: index, options: options }); }); }; // 动态改变进度条 Element.prototype.progress = function(filter, percent){ var ELEM = 'layui-progress'; var elem = $('.'+ ELEM +'[lay-filter='+ filter +']'); var elemBar = elem.find('.'+ ELEM +'-bar'); var text = elemBar.find('.'+ ELEM +'-text'); elemBar.css('width', function(){ return /^.+\/.+$/.test(percent) ? (new Function('return '+ percent)() * 100) + '%' : percent; }).attr('lay-percent', percent); text.text(percent); return this; }; var NAV_ELEM = '.layui-nav'; var NAV_ITEM = 'layui-nav-item'; var NAV_BAR = 'layui-nav-bar'; var NAV_TREE = 'layui-nav-tree'; var NAV_CHILD = 'layui-nav-child'; var NAV_CHILD_C = 'layui-nav-child-c'; var NAV_MORE = 'layui-nav-more'; var NAV_DOWN = 'layui-icon-down'; var NAV_ANIM = 'layui-anim layui-anim-upbit'; // 基础事件体 var call = { // Tab 点击 tabClick: function(obj){ obj = obj || {}; var options = obj.options || {}; var othis = obj.liElem || $(this); var parents = options.headerElem ? othis.parent() : othis.parents('.layui-tab').eq(0); var item = options.bodyElem ? $(options.bodyElem) : parents.children('.layui-tab-content').children('.layui-tab-item'); var elemA = othis.find('a'); var isJump = elemA.attr('href') !== 'javascript:;' && elemA.attr('target') === '_blank'; // 是否存在跳转 var unselect = typeof othis.attr('lay-unselect') === 'string'; // 是否禁用选中 var filter = parents.attr('lay-filter'); var hasId = othis.attr('lay-id'); // 下标 var index = 'index' in obj ? obj.index : othis.parent().children('li').index(othis); // 若非强制切换,则根据 tabBeforeChange 事件的返回结果决定是否切换 if (!obj.force) { var liThis = othis.siblings('.' + THIS); var shouldChange = layui.event.call(this, MOD_NAME, 'tabBeforeChange('+ filter +')', { elem: parents, from: { index: othis.parent().children('li').index(liThis), id: liThis.attr('lay-id') }, to: { index: index, id: hasId }, }); if(shouldChange === false) return; } // 执行切换 if(!(isJump || unselect)){ othis.addClass(THIS).siblings().removeClass(THIS); if(hasId){ var contentElem = item.filter('[lay-id="' + hasId + '"]'); contentElem = contentElem.length ? contentElem : item.eq(index); contentElem.addClass(SHOW).siblings().removeClass(SHOW); }else{ item.eq(index).addClass(SHOW).siblings().removeClass(SHOW); } } layui.event.call(this, MOD_NAME, 'tab('+ filter +')', { elem: parents, index: index, id: hasId }); } // Tab 删除 ,tabDelete: function(obj){ obj = obj || {}; var li = obj.liElem || $(this).parent(); var index = li.parent().children('li').index(li); var tabElem = li.closest('.layui-tab'); var item = tabElem.children('.layui-tab-content').children('.layui-tab-item'); var filter = tabElem.attr('lay-filter'); var hasId = li.attr('lay-id'); // 若非强制删除,则根据 tabBeforeDelete 事件的返回结果决定是否删除 if (!obj.force) { var shouldClose = layui.event.call(li[0], MOD_NAME, 'tabBeforeDelete('+ filter +')', { elem: tabElem, index: index, id: hasId }); if(shouldClose === false) return; } if(li.hasClass(THIS)){ if (li.next()[0] && li.next().is('li')){ call.tabClick.call(li.next()[0], { index: index + 1 }); } else if (li.prev()[0] && li.prev().is('li')){ call.tabClick.call(li.prev()[0], null, index - 1); } } li.remove(); if(hasId){ var contentElem = item.filter('[lay-id="' + hasId + '"]'); contentElem = contentElem.length ? contentElem : item.eq(index) contentElem.remove() }else{ item.eq(index).remove(); } setTimeout(function(){ call.tabAuto(null, tabElem); }, 50); layui.event.call(this, MOD_NAME, 'tabDelete('+ filter +')', { elem: tabElem, index: index, id: hasId }); } // Tab 自适应 ,tabAuto: function(spread, elem){ var SCROLL = 'layui-tab-scroll'; var MORE = 'layui-tab-more'; var BAR = 'layui-tab-bar'; var CLOSE = 'layui-tab-close'; var that = this; var targetElem = elem || $('.layui-tab'); targetElem.each(function(){ var othis = $(this); var title = othis.children('.layui-tab-title'); var item = othis.children('.layui-tab-content').children('.layui-tab-item'); var STOPE = 'lay-stope="tabmore"'; var span = $(''); if(that === window && device.ie != 8){ // call.hideTabMore(true) } // 开启关闭图标 var allowclose = othis.attr('lay-allowclose'); if(allowclose && allowclose !== 'false'){ title.find('li').each(function(){ var li = $(this); if(!li.find('.'+CLOSE)[0] && li.attr('lay-allowclose') !== 'false'){ var close = $(''); close.on('click', function(e) { call.tabDelete.call(this, { e: e }); }); li.append(close); } }); } if(typeof othis.attr('lay-unauto') === 'string') return; // 响应式 if( title.prop('scrollWidth') > title.outerWidth() + 1 || ( title.find('li').length && title.height() > function(height){ return height + height/2; }(title.find('li').eq(0).height()) ) ){ // 若执行是来自于切换,则自动展开 ( spread === 'change' && title.data('LAY_TAB_CHANGE') ) && title.addClass(MORE); if(title.find('.'+BAR)[0]) return; title.append(span); othis.attr('overflow', ''); // 展开图标事件 span.on('click', function(e){ var isSpread = title.hasClass(MORE); title[isSpread ? 'removeClass' : 'addClass'](MORE); }); } else { title.find('.'+ BAR).remove(); othis.removeAttr('overflow'); } }); } // 隐藏更多 Tab ,hideTabMore: function(e){ var tsbTitle = $('.layui-tab-title'); if(e === true || $(e.target).attr('lay-stope') !== 'tabmore'){ tsbTitle.removeClass('layui-tab-more'); tsbTitle.find('.layui-tab-bar').attr('title',''); } } //点击一级菜单 /* ,clickThis: function(){ var othis = $(this), parents = othis.parents(NAV_ELEM) ,filter = parents.attr('lay-filter') ,elemA = othis.find('a') ,unselect = typeof othis.attr('lay-unselect') === 'string'; if(othis.find('.'+NAV_CHILD)[0]) return; if(!(elemA.attr('href') !== 'javascript:;' && elemA.attr('target') === '_blank') && !unselect){ parents.find('.'+THIS).removeClass(THIS); othis.addClass(THIS); } layui.event.call(this, MOD_NAME, 'nav('+ filter +')', othis); } ) */ // 点击菜单 - a 标签触发 ,clickThis: function() { var othis = $(this); var parents = othis.closest(NAV_ELEM); var filter = parents.attr('lay-filter'); var parent = othis.parent() ; var child = othis.siblings('.'+ NAV_CHILD); var unselect = typeof parent.attr('lay-unselect') === 'string'; // 是否禁用选中 // 满足点击选中的条件 if (!(othis.attr('href') !== 'javascript:;' && othis.attr('target') === '_blank') && !unselect) { if (!child[0]) { parents.find('.'+ THIS).removeClass(THIS); parent.addClass(THIS); } } // 若为垂直菜单 if (parents.hasClass(NAV_TREE)) { var NAV_ITEMED = NAV_ITEM + 'ed'; // 用于标注展开状态 var needExpand = !parent.hasClass(NAV_ITEMED); // 是否执行展开 var ANIM_MS = 200; // 动画过渡毫秒数 // 动画执行完成后的操作 var complete = function() { $(this).css({ "display": "" // 剔除动画生成的 style display,以适配外部样式的状态重置 }); // 避免导航滑块错位 parents.children('.'+ NAV_BAR).css({ opacity: 0 }) }; // 是否正处于动画中的状态 if (child.is(':animated')) return; // 剔除可能存在的 CSS3 动画类 child.removeClass(NAV_ANIM); // 若有子菜单,则对其执行展开或收缩 if (child[0]) { if (needExpand) { // 先执行 slideDown 动画,再标注展开状态样式,避免元素 `block` 状态导致动画无效 child.slideDown(ANIM_MS, complete); parent.addClass(NAV_ITEMED); } else { // 先取消展开状态样式,再将元素临时显示,避免 `none` 状态导致 slideUp 动画无效 parent.removeClass(NAV_ITEMED); child.show().slideUp(ANIM_MS, complete); } // 手风琴 --- 收缩兄弟展开项 if (typeof parents.attr('lay-accordion') === 'string' || parents.attr('lay-shrink') === 'all') { var parentSibs = parent.siblings('.'+ NAV_ITEMED); parentSibs.removeClass(NAV_ITEMED); parentSibs.children('.'+ NAV_CHILD).show().stop().slideUp(ANIM_MS, complete); } } } layui.event.call(this, MOD_NAME, 'nav('+ filter +')', othis); } // 折叠面板 ,collapse: function(){ var othis = $(this); var icon = othis.find('.layui-colla-icon'); var elemCont = othis.siblings('.layui-colla-content'); var parents = othis.parents('.layui-collapse').eq(0); var filter = parents.attr('lay-filter'); var isNone = elemCont.css('display') === 'none'; // 是否手风琴 if(typeof parents.attr('lay-accordion') === 'string'){ var show = parents.children('.layui-colla-item').children('.'+SHOW); show.siblings('.layui-colla-title').children('.layui-colla-icon').html(''); show.removeClass(SHOW); } elemCont[isNone ? 'addClass' : 'removeClass'](SHOW); icon.html(isNone ? '' : ''); layui.event.call(this, MOD_NAME, 'collapse('+ filter +')', { title: othis ,content: elemCont ,show: isNone }); } }; // 初始化元素操作 Element.prototype.init = function(type, filter){ var that = this, elemFilter = function(){ return (typeof filter === 'string' && filter) ? ('[lay-filter="' + filter +'"]') : ''; }(), items = { // Tab 选项卡 tab: function(elem){ var TAB_ELEM = '.layui-tab'; var targetElem = elem || $(TAB_ELEM + elemFilter); call.tabAuto.call({}, null, targetElem); } // 导航菜单 ,nav: function(elem){ var TIME = 200; var timer = {}; var timerMore = {}; var timeEnd = {}; var NAV_TITLE = 'layui-nav-title'; // 滑块跟随 var follow = function(bar, nav, index) { var othis = $(this); var child = othis.find('.'+NAV_CHILD); // 是否垂直导航菜单 if (nav.hasClass(NAV_TREE)) { // 无子菜单时跟随 if (!child[0]) { var thisA = othis.children('.'+ NAV_TITLE); bar.css({ top: othis.offset().top - nav.offset().top, height: (thisA[0] ? thisA : othis).outerHeight(), opacity: 1 }); } } else { child.addClass(NAV_ANIM); // 若居中对齐 if (child.hasClass(NAV_CHILD_C)) { child.css({ left: -(child.outerWidth() - othis.width()) / 2 }); } // 滑块定位 if (child[0]) { // 若有子菜单,则滑块消失 bar.css({ left: bar.position().left + bar.width() / 2, width: 0, opacity: 0 }); } else { // bar 跟随 bar.css({ left: othis.position().left + parseFloat(othis.css('marginLeft')), top: othis.position().top + othis.height() - bar.height() }); } // 渐显滑块并适配宽度 timer[index] = setTimeout(function() { bar.css({ width: child[0] ? 0 : othis.width(), opacity: child[0] ? 0 : 1 }); }, device.ie && device.ie < 10 ? 0 : TIME); // 显示子菜单 clearTimeout(timeEnd[index]); if (child.css('display') === 'block') { clearTimeout(timerMore[index]); } timerMore[index] = setTimeout(function(){ child.addClass(SHOW); othis.find('.'+NAV_MORE).addClass(NAV_MORE+'d'); }, 300); } }; // 遍历导航 var targetElem = elem || $(NAV_ELEM + elemFilter); targetElem.each(function(index) { var othis = $(this); var bar = $(''); var itemElem = othis.find('.'+NAV_ITEM); // hover 滑动效果 var hasBarElem = othis.find('.'+NAV_BAR)[0]; if (hasBarElem) hasBarElem.remove(); othis.append(bar); ( othis.hasClass(NAV_TREE) ? itemElem.find('dd,>.'+ NAV_TITLE) : itemElem ).off('mouseenter.lay_nav').on('mouseenter.lay_nav', function() { follow.call(this, bar, othis, index); }).off('mouseleave.lay_nav').on('mouseleave.lay_nav', function() { // 鼠标移出 // 是否为垂直导航 if (othis.hasClass(NAV_TREE)) { bar.css({ height: 0, opacity: 0 }); } else { // 隐藏子菜单 clearTimeout(timerMore[index]); timerMore[index] = setTimeout(function(){ othis.find('.'+ NAV_CHILD).removeClass(SHOW); othis.find('.'+ NAV_MORE).removeClass(NAV_MORE +'d'); }, 300); } }); // 鼠标离开当前菜单时 othis.off('mouseleave.lay_nav').on('mouseleave.lay_nav', function() { clearTimeout(timer[index]) timeEnd[index] = setTimeout(function() { if (!othis.hasClass(NAV_TREE)) { bar.css({ width: 0, left: bar.position().left + bar.width() / 2, opacity: 0 }); } }, TIME); }); // 展开子菜单 itemElem.find('a').each(function() { var thisA = $(this); var parent = thisA.parent(); var child = thisA.siblings('.'+ NAV_CHILD); // 输出小箭头 if (child[0] && !thisA.children('.'+ NAV_MORE)[0]) { thisA.append(''); } thisA.off('click', call.clickThis).on('click', call.clickThis); // 点击菜单 }); }); } //面包屑 ,breadcrumb: function(elem){ var ELEM = '.layui-breadcrumb'; var targetElem = elem || $(ELEM + elemFilter); targetElem.each(function(){ var othis = $(this) ,ATTE_SPR = 'lay-separator' ,separator = othis.attr(ATTE_SPR) || '/' ,aNode = othis.find('a'); if(aNode.next('span['+ ATTE_SPR +']')[0]) return; aNode.each(function(index){ if(index === aNode.length - 1) return; $(this).after(''+ separator +''); }); othis.css('visibility', 'visible'); }); } //进度条 ,progress: function(elem){ var ELEM = 'layui-progress'; var targetElem = elem || $('.' + ELEM + elemFilter); targetElem.each(function(){ var othis = $(this) ,elemBar = othis.find('.layui-progress-bar') ,percent = elemBar.attr('lay-percent'); elemBar.css('width', function(){ return /^.+\/.+$/.test(percent) ? (new Function('return '+ percent)() * 100) + '%' : percent; }); if(othis.attr('lay-showpercent')){ setTimeout(function(){ elemBar.html(''+ percent +''); },350); } }); } //折叠面板 ,collapse: function(elem){ var ELEM = 'layui-collapse'; var targetElem = elem || $('.' + ELEM + elemFilter); targetElem.each(function(){ var elemItem = $(this).find('.layui-colla-item') elemItem.each(function(){ var othis = $(this) ,elemTitle = othis.find('.layui-colla-title') ,elemCont = othis.find('.layui-colla-content') ,isNone = elemCont.css('display') === 'none'; //初始状态 elemTitle.find('.layui-colla-icon').remove(); elemTitle.append(''+ (isNone ? '' : '') +''); //点击标题 elemTitle.off('click', call.collapse).on('click', call.collapse); }); }); } }; if(type && typeof filter === 'object' && filter instanceof $){ var targetElem = filter; return items[type](targetElem); } return items[type] ? items[type]() : layui.each(items, function(index, item){ item(); }); }; Element.prototype.render = Element.prototype.init; var element = new Element(); var dom = $(document); $(function(){ element.render(); }); dom.on('click', '.layui-tab-title li', call.tabClick); // Tab 切换 // dom.on('click', call.hideTabMore); // 隐藏展开的 Tab $(window).on('resize', call.tabAuto); // 自适应 exports(MOD_NAME, element); });