diff --git a/src/css/modules/code.css b/src/css/modules/code.css index 56e8c6a6..a0188666 100644 --- a/src/css/modules/code.css +++ b/src/css/modules/code.css @@ -6,18 +6,18 @@ html #layuicss-skincodecss{display:none; position: absolute; width:1989px;} /* 默认风格 */ -.layui-code-view{display: block; position: relative; margin: 10px 0; padding: 0; border: 1px solid #eee; border-left-width: 6px; background-color: #FAFAFA; color: #333; font-family: Courier New; font-size: 13px;} +.layui-code-view{display: block; position: relative; margin: 11px 0; padding: 0; border: 1px solid #eee; border-left-width: 6px; background-color: #FAFAFA; color: #333; font-family: Courier New; font-size: 13px;} .layui-code-title{position: relative; padding: 0 10px; height: 40px; line-height: 40px; border-bottom: 1px solid #eee; font-size: 12px;} .layui-code-title > .layui-code-about{position: absolute; right: 10px; top: 0; color: #B7B7B7;} .layui-code-about > a{padding-left: 10px;} .layui-code-view > .layui-code-ol, -.layui-code-view > .layui-code-ul{position: relative; overflow: auto;} -.layui-code-view > .layui-code-ol > li{position: relative; margin-left: 45px; line-height: 20px; padding: 0 10px; border-left: 1px solid #e2e2e2; list-style-type: decimal-leading-zero; *list-style-type: decimal; background-color: #fff;} +.layui-code-view > .layui-code-ul{max-height: 100%; padding: 0 !important; position: relative; overflow: auto;} +.layui-code-view > .layui-code-ol > li{position: relative; margin-top: 0 !important; margin-left: 45px !important; line-height: 20px; padding: 0 10px !important; border-left: 1px solid #e2e2e2; list-style-type: decimal-leading-zero; *list-style-type: decimal; background-color: #fff;} .layui-code-view > .layui-code-ol > li:first-child, -.layui-code-view > .layui-code-ul > li:first-child{padding-top: 10px;} +.layui-code-view > .layui-code-ul > li:first-child{padding-top: 10px !important;} .layui-code-view > .layui-code-ol > li:last-child, -.layui-code-view > .layui-code-ul > li:last-child{padding-bottom: 10px;} -.layui-code-view > .layui-code-ul > li{position: relative; line-height: 20px; padding: 0 10px; list-style-type: none; *list-style-type: none; background-color: #fff;} +.layui-code-view > .layui-code-ul > li:last-child{padding-bottom: 10px !important;} +.layui-code-view > .layui-code-ul > li{position: relative; line-height: 20px; padding: 0 10px !important; list-style-type: none; *list-style-type: none; background-color: #fff;} .layui-code-view pre{margin: 0;} /* 深色风格 */ @@ -28,5 +28,23 @@ html #layuicss-skincodecss{display:none; position: absolute; width:1989px;} .layui-code-dark > .layui-code-ul > li{margin-left: 6px;} /* 代码预览 */ -.layui-code-demo .layui-code{visibility: visible !important; margin: -15px; border-top: none; border-right: none; border-bottom: none;} -.layui-code-demo .layui-tab-content{padding: 15px; border-top: none} \ No newline at end of file +.layui-code textarea{display: none;} +.layui-code-preview > .layui-code{margin: 0;} +.layui-code-preview > .layui-tab{position: relative; z-index: 1; margin-bottom: 0;} +.layui-code-preview > .layui-tab > .layui-tab-title{border-bottom: none;} +.layui-code-preview > .layui-code > .layui-code-title{display: none;} +.layui-code-preview .layui-code-item{display: none;} +.layui-code-preview .layui-code-view > .layui-code-ol > li{} +.layui-code-item-preview{position: relative; padding: 16px;} +.layui-code-item-preview > iframe{position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: none;} + +/* 工具栏 */ +.layui-code-tools{position: absolute; right: 11px; top: 3px;} +.layui-code-tools > i{display: inline-block; margin-left: 6px; padding: 3px; cursor: pointer;} + +/* 全屏风格 */ +.layui-code-full{position: fixed; left: 0; top: 0; z-index: 1111111; width: 100%; height: 100%; background-color: #fff;} +.layui-code-full .layui-code-item{width: 100% !important; border-width: 0 !important; border-top-width: 1px !important;} +.layui-code-full .layui-code-item, +.layui-code-full .layui-code-ol, +.layui-code-full .layui-code-ul{height: calc(100vh - 51px) !important; box-sizing: border-box;} \ No newline at end of file diff --git a/src/modules/code.js b/src/modules/code.js index 47a1fc5d..68da0494 100644 --- a/src/modules/code.js +++ b/src/modules/code.js @@ -1,22 +1,38 @@ /** * code - * 代码块简易修饰 + * Code 预览组件 */ -layui.define(['lay', 'util'], function(exports){ +layui.define(['lay', 'util', 'element', 'form'], function(exports){ "use strict"; var $ = layui.$; var util = layui.util; + var element = layui.element; + var form = layui.form; - var ELEM_TITLE = 'layui-code-title'; + // 常量 + var CONST = { + ELEM_VIEW: 'layui-code-view', + ELEM_TITLE: 'layui-code-title', + ELEM_FULL: 'layui-code-full', + ELEM_PREVIEW: 'layui-code-preview', + ELEM_ITEM: 'layui-code-item', + ELEM_SHOW: 'layui-show' + }; // 默认参数项 var config = { elem: '.layui-code', // 元素选择器 title: '</>', // 标题 about: '', // 右上角信息 - ln: true // 是否显示行号 + ln: true, // 是否显示行号 + header: false, // 是否显示头部区域 + + text: { + code: util.escape(''), + preview: 'Preview' + } }; var trim = function(str){ @@ -25,7 +41,7 @@ layui.define(['lay', 'util'], function(exports){ // export api exports('code', function(options){ - var opts = options = $.extend({}, config, options); + var opts = options = $.extend(true, {}, config, options); // 目标元素是否存在 options.elem = $(options.elem); @@ -37,7 +53,7 @@ layui.define(['lay', 'util'], function(exports){ var html = trim(othis.html()); // 合并属性上的参数,并兼容旧版本属性写法 lay-* - var options = $.extend({}, opts, lay.options(item), function(obj){ + var options = $.extend(true, {}, opts, lay.options(item), function(obj){ var attrs = ['title', 'height', 'encode', 'skin', 'about']; layui.each(attrs, function(i, attr){ var value = othis.attr('lay-'+ attr); @@ -48,12 +64,181 @@ layui.define(['lay', 'util'], function(exports){ return obj; }({})); + // 获得代码 + var codes = function(){ + var arr = []; + var textarea = othis.children('textarea'); + + // 若内容放置在 textarea 中 + textarea.each(function(){ + arr.push(trim(this.value)); + }); + + if(textarea[0]){ + html = util.escape(arr.join('')); + } + + // 内容直接放置在元素外层 + if(arr.length === 0){ + arr.push(trim(othis.html())); + } + + return arr; + }(); + + // 是否开启预览 + if(options.preview){ + var FILTER_VALUE = 'LAY-CODE-DF-'+ index; + var layout = options.layout || ['code', 'preview']; + var isIframePreview = options.preview === 'iframe'; + + // 追加 Tab 组件 + var elemView = $('
'); + var elemTabView = $('
'); + var elemHeaderView = $('
'); + var elemPreviewView = $('
'); + var elemToolbar = $('
'); + var elemViewHas = othis.prev('.' + CONST.ELEM_PREVIEW); + var elemPreviewViewHas = othis.next('.' + CONST.ELEM_ITEM +'-preview'); + + if(options.id) elemView.attr('id', options.id); + elemTabView.attr('lay-filter', FILTER_VALUE); + + // 标签头 + layui.each(layout, function(i, v){ + var li = $('
  • '); + if(i === 0) li.addClass('layui-this'); + li.html(options.text[v]); + elemHeaderView.append(li); + }); + + // 工具栏 + var tools = { + 'full': { + className: 'screen-full', + title: ['最大化显示', '还原显示'], + event: function(el, type){ + var elemView = el.closest('.'+ CONST.ELEM_PREVIEW); + var classNameFull = 'layui-icon-'+ this.className; + var classNameRestore = 'layui-icon-screen-restore'; + var title = this.title; + var html = $('html,body'); + var ELEM_SCOLLBAR_HIDE = 'layui-scollbar-hide'; + + if(el.hasClass(classNameFull)){ + elemView.addClass(CONST.ELEM_FULL); + el.removeClass(classNameFull).addClass(classNameRestore); + el.attr('title', title[1]); + html.addClass(ELEM_SCOLLBAR_HIDE); + } else { + elemView.removeClass(CONST.ELEM_FULL); + el.removeClass(classNameRestore).addClass(classNameFull); + el.attr('title', title[0]); + html.removeClass(ELEM_SCOLLBAR_HIDE); + } + } + }, + 'window': { + className: 'release', + title: ['在新窗口预览'], + event: function(el, type){ + util.openWin({ + content: codes.join('') + }); + } + } + }; + elemToolbar.on('click', '>i', function(){ // 工具栏事件 + var oi = $(this); + var type = oi.data('type'); + typeof tools[type].event === 'function' && tools[type].event(oi, type); + typeof options.toolsEvent === 'function' && options.toolsEvent(oi, type); + }); + layui.each(options.tools, function(i, v){ + var className = (tools[v] && tools[v].className) || v; + var title = tools[v].title || ['']; + elemToolbar.append( + '' + ); + }); + + // 移除旧结构 + if(elemViewHas[0]) elemViewHas.remove(); + if(elemPreviewViewHas[0]) elemPreviewViewHas.remove(); + + elemTabView.append(elemHeaderView); // 追加标签头 + options.tools && elemTabView.append(elemToolbar); // 追加工具栏 + othis.wrap(elemView).addClass(CONST.ELEM_ITEM).before(elemTabView); // 追加标签结构 + + + // 追加预览 + if(isIframePreview){ + elemPreviewView.html(''); + } + + // 执行预览 + var run = function(thisItemBody){ + var iframe = thisItemBody.children('iframe')[0]; + if(isIframePreview && iframe){ + iframe.srcdoc = codes.join(''); + } else { + thisItemBody.html(codes.join('')); + } + // 回调的返回参数 + var params = { + container: thisItemBody, + render: function(){ + form.render(thisItemBody.find('.layui-form')); + element.render(); + } + }; + // 当前实例预览完毕后的回调 + setTimeout(function(){ + typeof options.done === 'function' && options.done(params); + },3); + }; + + if(layout[0] === 'preview'){ + elemPreviewView.addClass(CONST.ELEM_SHOW); + othis.before(elemPreviewView); + run(elemPreviewView); + } else { + othis.addClass(CONST.ELEM_SHOW).after(elemPreviewView); + } + + // 内容项初始化样式 + options.codeStyle = [options.style, options.codeStyle].join(''); + options.previewStyle = [options.style, options.previewStyle].join(''); + // othis.attr('style', options.codeStyle); + elemPreviewView.attr('style', options.previewStyle); + + // tab change + element.on('tab('+ FILTER_VALUE +')', function(data){ + var $this = $(this); + var thisElem = $(data.elem).closest('.'+ CONST.ELEM_PREVIEW); + var elemItemBody = thisElem.find('.'+ CONST.ELEM_ITEM); + var thisItemBody = elemItemBody.eq(data.index); + + elemItemBody.removeClass(CONST.ELEM_SHOW); + thisItemBody.addClass(CONST.ELEM_SHOW); + + if($this.attr('lay-id') === 'preview'){ + run(thisItemBody); + } + }); + }; + + // 有序或无序列表 var listTag = options.ln ? 'ol' : 'ul'; var listElem = $('<'+ listTag +' class="layui-code-'+ listTag +'">'); // header - var headerElem = $('
    '); + var headerElem = $('
    '); // 添加组件 clasName othis.addClass('layui-code-view layui-box'); @@ -72,7 +257,7 @@ layui.define(['lay', 'util'], function(exports){ othis.html(listElem.html('
  • ' + html + '
  • ')); // 创建 header - if(!othis.children('.'+ ELEM_TITLE)[0]){ + if(options.header && !othis.children('.'+ CONST.ELEM_TITLE)[0]){ headerElem.html(options.title + ( options.about ? '
    ' + options.about + '
    ' @@ -81,6 +266,11 @@ layui.define(['lay', 'util'], function(exports){ othis.prepend(headerElem); } + // 所有实例渲染完毕后的回调 + if(options.elem.length === index + 1){ + typeof options.allDone === 'function' && options.allDone(); + } + // 按行数适配左边距 (function(autoIncNums){ if(autoIncNums > 0){ @@ -88,10 +278,12 @@ layui.define(['lay', 'util'], function(exports){ } })(Math.floor(listElem.find('li').length/100)); - // 限制最大高度 - if(options.height){ + // 限制 Code 最大高度 + if(options.height){ // 兼容旧版本 listElem.css('max-height', options.height); } + // Code 内容区域样式 + listElem.attr('style', options.codeStyle); });