release v2.8.17

release v2.8.17
pull/1373/head^2 v2.8.17
贤心 2023-09-11 12:06:27 +08:00 committed by GitHub
commit 8309c42e6c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 1586 additions and 774 deletions

View File

@ -1,62 +1,67 @@
name: 😇 问题反馈 name: 😇 问题反馈
description: 使用 Layui 过程中遇到的 Bug、异常或其他困惑。 description: 使用 Layui 过程中遇到的 Bug、异常或其他困惑。
title: "" title: ""
body: body:
- type: markdown - type: markdown
attributes: attributes:
value: | value: |
**请注意**:此处只接受 Layui 相关技术问题,其他如 layuiAdmin 或 layim 等主题相关问题请勿在此反馈。 **系统提示**:此处只接受 Layui 相关技术问题,其他如 layuiAdmin 或 LayIM 等主题相关问题请勿在此反馈。
<br><br> - type: checkboxes
同时,在反馈问题之前,请确保: attributes:
- 已查看官方使用文档:**https://layui.dev** ,但没有找到相关解决方案。 label: 议题条件
- 已在 **Issues** 中搜索过类似的问题,但没有找到相关解决方案。 options:
- type: input - label: 我确认已查看官方使用文档:**https://layui.dev** ,但没有找到相关解决方案。
attributes: required: true
label: 版本号 - label: 我确认已在 **Issues** 中搜索过类似的问题,但没有找到相关解决方案。
placeholder: 请提供您所使用的 Layui 版本号 required: true
validations: - type: input
required: true attributes:
- type: input label: 版本号
attributes: placeholder: 请提供您所使用的 Layui 版本号
label: 浏览器 validations:
placeholder: Chrome 115.0.5735.91(正式版本) 64 位) required: true
validations: - type: input
required: true attributes:
- type: dropdown label: 浏览器
id: type placeholder: Chrome 116.0.5845.111(正式版本) 64 位)
attributes: validations:
label: 问题类型 required: true
options: - type: dropdown
- 疑是 BUG id: type
- 报错提示 attributes:
- 功能困惑 label: 问题类型
validations: options:
required: true - 疑是 BUG
- type: textarea - 报错提示
attributes: - 功能困惑
label: 问题描述 validations:
placeholder: 请提供详细的问题描述和操作步骤等信息,以便我们也能够更轻松地将问题复现。 required: true
validations: - type: textarea
required: true attributes:
- type: textarea label: 问题描述
attributes: placeholder: 请提供详细的问题描述和操作步骤等信息,以便我们也能够更轻松地将问题复现。
label: 业务代码 validations:
description: 直接粘贴问题对应的 `HTML,CSS,JavaScript` 等代码到下面的文本框,无需书写 `Markdown` required: true
placeholder: 请提供与该问题对应的业务代码片段,以便我们更好地排查问题。 - type: textarea
render: auto attributes:
validations: label: 业务代码
required: true description: 直接粘贴问题对应的 `HTML,CSS,JavaScript` 等代码到下面的文本框,无需书写 `Markdown`
- type: textarea placeholder: 请提供与该问题对应的业务代码片段,以便我们更好地排查问题。
attributes: render: auto
label: 截图补充 validations:
placeholder: 如上述仍然无法准确地表述问题,可提供必要的截图(可直接粘贴上传) required: true
- type: input - type: textarea
attributes: attributes:
label: 演示地址 label: 截图补充
placeholder: 若能提供 CodePen、Stackblitz 或自主搭建的页面演示地址,将更有助于解决问题 placeholder: 如上述仍然无法准确地表述问题,可提供必要的截图(可直接粘贴上传)
- type: checkboxes - type: input
attributes: attributes:
label: 友好承诺 label: 演示地址
options: description: 若能提供 Stackblitz, CodePen 或自主搭建的页面演示地址,将更有助于解决问题
- label: 我承诺将本着相互尊重、理解和友善的态度进行交流,共同维护 Layui 良好的社区氛围。 placeholder: URL
required: true - type: checkboxes
attributes:
label: 友好承诺
options:
- label: 我承诺将本着相互尊重、理解和友善的态度进行交流,共同维护 Layui 良好的社区氛围。
required: true

View File

@ -1,6 +1,6 @@
### 😃 本次 PR 的变化性质 ### 😃 本次 PR 的变化性质
> 请至少勾选一项[ ] 内填写 x > 请至少勾选一项
- [ ] 功能新增 - [ ] 功能新增
- [x] 问题修复 - [x] 问题修复
@ -15,9 +15,8 @@
### ✅ 本次 PR 的满足条件 ### ✅ 本次 PR 的满足条件
> 请在申请合并之前,将符合条件的每一项进行勾选[ ] 内填写 x > 请在申请合并之前,将符合条件的每一项进行勾选
- [ ] 已提供在线演示地址(如:[codepen](https://codepen.io/))或无需演示 - [ ] 已提供在线演示地址(如:[codepen](https://codepen.io/), [stackblitz](https://stackblitz.com/))或无需演示
- [ ] 已对每一项的改动均测试通过 - [ ] 已对每一项的改动均测试通过
- [ ] 已提供具体的变化内容说明 - [ ] 已提供具体的变化内容说明

2
dist/css/layui.css vendored

File diff suppressed because one or more lines are too long

2
dist/layui.js vendored

File diff suppressed because one or more lines are too long

View File

@ -31,7 +31,7 @@ toc: true
| layui-hide-v | 设置元素为 `visibility: hidden` 不可见状态,且依旧占用空间 | | layui-hide-v | 设置元素为 `visibility: hidden` 不可见状态,且依旧占用空间 |
<h2 id="edge" lay-toc="{}">三角实体</h2> <h2 id="triangle" lay-toc="{}">三角实体</h2>
| className | 描述 | | className | 描述 |
| --- | --- | | --- | --- |
@ -66,6 +66,21 @@ toc: true
</textarea> </textarea>
</pre> </pre>
<h2 id="edge-distance" lay-toc="{}">内外边距</h2>
| className | 描述 |
| --- | --- |
| layui-padding-1 | 4px 内边距 |
| layui-padding-2 | 8px 内边距 |
| layui-padding-3 | 16px 内边距 |
| layui-padding-4 | 32px 内边距 |
| layui-padding-5 | 48px 内边距 |
| layui-margin-1 | 4px 外边距 |
| layui-margin-2 | 8px 外边距 |
| layui-margin-3 | 16px 外边距 |
| layui-margin-4 | 32px 外边距 |
| layui-margin-5 | 48px 外边距 |
<h2 id="bg" lay-toc="{hot: true}">背景颜色</h2> <h2 id="bg" lay-toc="{hot: true}">背景颜色</h2>
@ -167,4 +182,4 @@ toc: true
</body> </body>
</html> </html>
</textarea> </textarea>
</pre> </pre>

View File

@ -134,10 +134,22 @@ layout: ['code', 'preview']
工具图标将根据数组的排列顺序来显示,如: 工具图标将根据数组的排列顺序来显示,如:
``` ```
tools: ['full', 'window'] tools: [
'full',
'window',
// 自定义扩展工具 --- 2.8.17+
{
title: ['切换高亮主题'],
type: 'theme',
event: function(obj) {
console.log(obj); // 当前实例相关信息
// do something
}
}
]
``` ```
亦可自定义值,值对应[图标](../icon/) `className``layui-icon-` 后的名称,并通过 `toolsEvent` 回调函数中处理事件。 `type` 值对应[图标](../icon/) `className``layui-icon-` 后的名称。如图标:`layui-icon-theme`,那么 `type` 设置 `theme` 即可
</td> </td>
<td>array</td> <td>array</td>
@ -147,12 +159,12 @@ tools: ['full', 'window']
<td>toolsEvent <sup>2.8+</sup></td> <td>toolsEvent <sup>2.8+</sup></td>
<td> <td>
点击工具栏的回调函数,函数返回 `tools` 设置的名称,如: 点击工具栏的回调函数,功能同 `tools` 中的 `event`,只是需通过 `type` 属性来区分是哪个工具菜单。
``` ```
toolsEvent: function(othis, type){ toolsEvent: function(obj){
console.log(othis); // 当前图标元素对象 console.log(obj); // 当前实例相关信息
console.log(type); // tools 中设置的对应值 console.log(obj.type); // 当前实例相关信息
} }
``` ```
@ -197,7 +209,7 @@ text: {
<td>header <sup>2.8+</sup></td> <td>header <sup>2.8+</sup></td>
<td> <td>
是否开启 Code 栏头部区域 是否开启 Code 栏头部区域
</td> </td>
<td>boolean</td> <td>boolean</td>
@ -208,16 +220,6 @@ text: {
</td> </td>
</tr> </tr>
<tr> <tr>
<td>about</td>
<td>
设置 Code 栏头部右上角信息。必须开启 `header` 属性后有效。
</td>
<td>string</td>
<td>-</td>
</tr>
<tr>
<td>ln</td> <td>ln</td>
<td> <td>
@ -232,10 +234,10 @@ text: {
</td> </td>
</tr> </tr>
<tr> <tr>
<td>skin</td> <td>theme <sup>2.8.17+</sup></td>
<td> <td>
Code 容器的风格,可选值有: Code 容器的主题风格,可选值有:
- `light` 浅色模式(默认) - `light` 浅色模式(默认)
- `dark` 深色模式 - `dark` 深色模式
@ -256,6 +258,84 @@ Code 容器的风格,可选值有:
`true` `true`
</td>
</tr>
<tr>
<td>lang <sup>2.8.17+</sup></td>
<td>
指定语言类型。如:`lang: 'html'`
</td>
<td>string</td>
<td>-</td>
</tr>
<tr>
<td>langMarker <sup>2.8.17+</sup></td>
<td>
是否在代码区域右上角显示语言类型
</td>
<td>boolean</td>
<td>
`false`
</td>
</tr>
<tr>
<td>wordWrap <sup>2.8.17+</sup></td>
<td>
Code 文字是否自动换行
</td>
<td>boolean</td>
<td>
`true`
</td>
</tr>
<tr>
<td>highlighter <sup>2.8.17+</sup></td>
<td>
指定语法高亮器,可选值:
- `hljs` : 指定 `highlight.js`
- `prism` : 指定 `prism.js`
- `shiki` : 指定 `shiki.js`
</td>
<td>string</td>
<td>-</td>
</tr>
<tr>
<td>
[codeRender](#options.codeRender) <sup>2.8+</sup>
</td>
<td colspan="3">
<div id="options.codeRender" lay-pid="options" class="ws-anchor">
用于重新渲染 code譬如代码高亮处理。
</div>
```
codeRender: function(code, opts){
// 此处以 highlight.js 为例
return hljs.highlight(code, {language: opts.lang}).value;
}
```
code 组件语法高亮相关示例:
- <a href="https://stackblitz.com/edit/web-platform-hhftb4?file=index.html" rel="nofollow" target="_blank">highlight 和 prism 语法高亮示例</a>
- <a href="https://codepen.io/Sight-wcg/pen/GRPjQyG" rel="nofollow" target="_blank">shiki 语法高亮示例</a>
</td> </td>
</tr> </tr>
<tr> <tr>
@ -288,7 +368,7 @@ done: function(obj){
<td colspan="3"> <td colspan="3">
<div id="options.onCopy" lay-pid="options" class="ws-anchor"> <div id="options.onCopy" lay-pid="options" class="ws-anchor">
点击复制图标时的回调函数。 该回调一旦设定,则不再执行内置的复制操作。 点击复制图标时的回调函数。
</div> </div>
``` ```
@ -300,4 +380,4 @@ onCopy: function(code){
</td> </td>
</tr> </tr>
</tbody> </tbody>
</table> </table>

View File

@ -10,18 +10,37 @@ toc: true
<h2 id="api" lay-toc="{}">方法</h2> <h2 id="api" lay-toc="{}">方法</h2>
`layui.code(options);` `var codeInst = layui.code(options);`
- 参数 `options` : 基础属性配置项。[#详见属性](#options)。 - 参数 `options` : 基础属性配置项。[#详见属性](#options)。
属性除了在该方法中传递,也可以直接写在元素的 `lay-options` 属性上,如: 其中 `codeInst` <sup>2.8.17+</sup> 即实例返回的对象,包含对当前实例进行重载等方法成员,如:
<pre class="layui-code" lay-options="{preview: true, layout: ['code', 'preview']}"> ```
var codeInst = layui.code(options);
console.log(codeInst); // 查看所有成员
codeInst.config; // 当前实例配置项
codeInst.reload(options); // 重载
codeInst.reloadCode(options); // 仅重载 code
```
另外,属性除了在该方法中传递,也可以直接写在元素的 `lay-options` 属性上,如:
<pre class="layui-code" lay-options="{preview: true, codeStyle: 'height: 315px;', layout: ['code', 'preview']}">
<textarea> <textarea>
<pre class="layui-code code-demo" lay-options="{}"> <pre class="layui-code code-demo" lay-options="{}">
// 在里面放置任意的 code light theme
test light theme
test light theme
</pre>
<hr>
<pre class="layui-code code-demo" lay-options="{theme: 'dark'}">
dark theme
dark theme
dark theme
</pre> </pre>
<!-- import layui --> <!-- import layui -->
@ -40,4 +59,8 @@ layui.use(function(){
<div> <div>
{{- d.include("/code/detail/options.md") }} {{- d.include("/code/detail/options.md") }}
</div> </div>
<h2>小贴士</h2>
> code 组件可广泛应用于技术类文档、博客等页面,可轻松适配第三方主流语法高亮器。

View File

@ -26,7 +26,7 @@
<div class="layui-inline"> <div class="layui-inline">
<label class="layui-form-label">验证邮箱</label> <label class="layui-form-label">验证邮箱</label>
<div class="layui-input-inline"> <div class="layui-input-inline">
<input type="text" name="email" lay-verify="email" autocomplete="off" class="layui-input"> <input type="text" name="email" lay-verify="email" placeholder="有值时才校验" autocomplete="off" class="layui-input">
</div> </div>
</div> </div>
<div class="layui-inline"> <div class="layui-inline">
@ -205,10 +205,11 @@ layui.use(['form', 'laydate', 'util'], function(){
// 自定义验证规则 // 自定义验证规则
form.verify({ form.verify({
pass: [ pass: function(value) {
/^[\S]{6,12}$/, if (!/(.+){6,12}$/.test(value)) {
'密码必须6到12位且不能出现空格' return '密码必须 6 到 12 位';
] }
}
}); });
// 指定开关事件 // 指定开关事件
@ -254,4 +255,4 @@ layui.use(['form', 'laydate', 'util'], function(){
} }
}); });
}); });
</script> </script>

View File

@ -13,8 +13,7 @@ layui.use(function(){
// 自定义验证规则,如下以验证用户名和密码为例 // 自定义验证规则,如下以验证用户名和密码为例
form.verify({ form.verify({
// 函数写法 // 参数 value 为表单的值;参数 item 为表单元素
// 参数 value 为表单的值;参数 item 为表单的 DOM 对象
username: function(value, item){ username: function(value, item){
if(!new RegExp("^[a-zA-Z0-9_\u4e00-\u9fa5\\s·]+$").test(value)){ if(!new RegExp("^[a-zA-Z0-9_\u4e00-\u9fa5\\s·]+$").test(value)){
return '用户名不能有特殊字符'; return '用户名不能有特殊字符';
@ -22,15 +21,17 @@ layui.use(function(){
if(/(^_)|(__)|(_+$)/.test(value)) return '用户名首尾不能出现 _ 下划线'; if(/(^_)|(__)|(_+$)/.test(value)) return '用户名首尾不能出现 _ 下划线';
if(/^\d+$/.test(value)) return '用户名不能全为数字'; if(/^\d+$/.test(value)) return '用户名不能全为数字';
// 若不想自动弹出默认提示框,可返回 true这时通过其他提示方式替代v2.5.7 新增) // 若不想自动弹出默认提示框,可返回 true这时可通过其他提示方式替代v2.5.7 新增)
if(value === 'xxx'){ if(value === 'xxx'){
alert('用户名不能为敏感词'); alert('用户名不能为敏感词');
return true; return true;
} }
}, },
// 数组写法。 password: function(value) {
// 数组中两个成员值分别代表:[正则表达式、正则匹配不符时的提示文字] if (!/^[\S]{6,12}$/.test(value)) {
password: [/^[\S]{6,12}$/, '密码必须为6到12位的非空字符'] return '密码必须为 6 到 12 位的非空字符';
}
}
}); });
// 提交事件 // 提交事件
@ -48,4 +49,4 @@ layui.use(function(){
return false; // 阻止默认 form 跳转 return false; // 阻止默认 form 跳转
}); });
}) })
</script> </script>

View File

@ -111,7 +111,7 @@ form 还可以借助*栅格*实现更灵活的响应式布局。
| --- | --- | --- | | --- | --- | --- |
| title | 自定义 | 设置表单元素标题,一般用于 `checkbox,radio` 元素 | | title | 自定义 | 设置表单元素标题,一般用于 `checkbox,radio` 元素 |
| lay-filter | 自定义 | 设置表单元素的过滤器,以便用于执行相关方法时的参数匹配 | | lay-filter | 自定义 | 设置表单元素的过滤器,以便用于执行相关方法时的参数匹配 |
| lay-verify | `required`必填项 <br>`phone`手机号 <br>`email`邮箱 <br>`url`网址<br>`number`数字<br>`date`日期<br>`identity`身份证<hr>`自定义规则值` | 设置表单项的验证规则,支持单条或多条规则(多条用`\|`分隔),如:<br>`lay-verify="required"` <br>`lay-verify="required\|email"`<br>`lay-verify="其他自定义规则值"` <hr>自定义规则的用法:[#详见](#verify) | | lay-verify | `required`必填项 <br>`phone`手机号 <br>`email`邮箱 <br>`url`网址<br>`number`数字<br>`date`日期<br>`identity`身份证<hr>`自定义规则值` | 设置表单项的验证规则,支持单条或多条规则(多条用`\|`分隔),如:<br>`lay-verify="required"` <br>`lay-verify="required\|email"`<br>`lay-verify="其他自定义规则值"` <hr>自定义规则的用法:[#详见](#verify)<hr>注:<sup>2.8.3</sup> 版本中调整了内置规则,不再强制必填。<br>如需保留必填,可叠加 `required` 规则,如: <br> `lay-verify="required\|number"` |
| lay-vertype | `tips`吸附层<br>`alert` 对话框<br>`msg` 默认 | 设置验证异常时的提示层模式 | | lay-vertype | `tips`吸附层<br>`alert` 对话框<br>`msg` 默认 | 设置验证异常时的提示层模式 |
| lay-reqtext | 自定义 | 设置*必填项*`lay-verify="required"`)的默认提示文本 | | lay-reqtext | 自定义 | 设置*必填项*`lay-verify="required"`)的默认提示文本 |
| lay-affix | [#详见](input.html#affix) | 输入框动态点缀,`<input type="text">`元素 **私有属性** | | lay-affix | [#详见](input.html#affix) | 输入框动态点缀,`<input type="text">`元素 **私有属性** |
@ -408,7 +408,6 @@ form.on('select(test)', function(data){
| 属性名 | 描述 | 类型 | 默认值 | | 属性名 | 描述 | 类型 | 默认值 |
| --- | --- | --- | --- | | --- | --- | --- | --- |
| autocomplete | 设置 input 框的 `autocomplete` 属性初始值 | string | - | | autocomplete | 设置 input 框的 `autocomplete` 属性初始值 | string | - |
| verIncludeRequired <sup>2.8.4+</sup> | 验证规则中是否同时包含必填。 form 组件在 `2.8.3` 版本中调整了内置校验规则,即:仅当非空时进行校验,避免强制携带必填的校验规则。如需保留之前的验证规则(即同时校验必填),可将该属性设置为 `true`。但一般还是建议将必填项放置在 `lay-verify` 属性上,如: `lay-verify="required\|number"` | boolean | `false` |
该方法用于对 form 组件进行全局设置。 该方法用于对 form 组件进行全局设置。

View File

@ -109,12 +109,12 @@ npm i layui
点击上方 `Preview` 标签可进行效果预览。 点击上方 `Preview` 标签可进行效果预览。
<h2 id="help">其他帮助</h2> <h3 id="help">其他帮助</h3>
- <a href="https://codepen.io/layui/pen/bGxZXrd" target="_blank" rel="nofollow">在线测试</a> - <a href="https://layui.dev/playground/2/">在线测试</a>
- <a href="https://github.com/Sight-wcg/layui-theme-dark" target="_blank">深色主题</a> (社区贡献) - <a href="https://github.com/Sight-wcg/layui-theme-dark" rel="nofollow" target="_blank">深色主题</a> (社区贡献)
## 初识寄语 ## 初识寄语
> 愿 Layui 从此成为您得心应手的 Web 界面解决方案,化作您方寸屏幕前的亿万字节! > 愿 Layui 从此成为您得心应手的 Web 界面解决方案,化作您方寸屏幕前的亿万字节!

View File

@ -6,6 +6,8 @@
</textarea> </textarea>
</pre> </pre>
<div class="ws-docs-showcase" style="margin-top: 16px;"></div>
<h3 id="type" lay-toc="{level: 2, hot: true}">弹层类型</h3> <h3 id="type" lay-toc="{level: 2, hot: true}">弹层类型</h3>
<pre class="layui-code" lay-options="{preview: true, codeStyle: 'height: 535px;', text: {preview: '弹层类型'}, layout: ['preview', 'code'], tools: ['full']}"> <pre class="layui-code" lay-options="{preview: true, codeStyle: 'height: 535px;', text: {preview: '弹层类型'}, layout: ['preview', 'code'], tools: ['full']}">
@ -98,4 +100,4 @@
### 小贴士 ### 小贴士
> 事实上 layer 丰富的基础属性,可足够让您的弹出层变得千变万化,为了避免占用太多篇幅,就不做过多演示了。 > 事实上 layer 丰富的基础属性,可足够让您的弹出层变得千变万化,为了避免占用太多篇幅,就不做过多演示了。

View File

@ -64,7 +64,7 @@ layui.use(function(){
{ {
"alt": "浩瀚宇宙", "alt": "浩瀚宇宙",
"pid": 5, "pid": 5,
"src": "https://unpkg.com/outeres/demo/outer-space.jpg", "src": "https://unpkg.com/outeres@0.1.1/demo/outer-space.jpg",
} }
] ]
}, },
@ -80,17 +80,17 @@ layui.use(function(){
{ {
"alt": "layer", "alt": "layer",
"pid": 1, "pid": 1,
"src": "https://unpkg.com/outeres/demo/layer.png", "src": "https://unpkg.com/outeres@0.1.1/demo/layer.png",
}, },
{ {
"alt": "壁纸", "alt": "壁纸",
"pid": 3, "pid": 3,
"src": "https://unpkg.com/outeres/demo/000.jpg", "src": "https://unpkg.com/outeres@0.1.1/demo/000.jpg",
}, },
{ {
"alt": "浩瀚宇宙", "alt": "浩瀚宇宙",
"pid": 5, "pid": 5,
"src": "https://unpkg.com/outeres/demo/outer-space.jpg", "src": "https://unpkg.com/outeres@0.1.1/demo/outer-space.jpg",
} }
] ]
} }

View File

@ -84,17 +84,17 @@ layui.use(function(){
{ {
"alt": "layer", "alt": "layer",
"pid": 1, "pid": 1,
"src": "https://unpkg.com/outeres/demo/layer.png", "src": "https://unpkg.com/outeres@0.1.1/demo/layer.png",
}, },
{ {
"alt": "壁纸", "alt": "壁纸",
"pid": 3, "pid": 3,
"src": "https://unpkg.com/outeres/demo/000.jpg", "src": "https://unpkg.com/outeres@0.1.1/demo/000.jpg",
}, },
{ {
"alt": "浩瀚宇宙", "alt": "浩瀚宇宙",
"pid": 5, "pid": 5,
"src": "https://unpkg.com/outeres/demo/outer-space.jpg", "src": "https://unpkg.com/outeres@0.1.1/demo/outer-space.jpg",
} }
] ]
} }
@ -102,4 +102,4 @@ layui.use(function(){
} }
}); });
}); });
</script> </script>

View File

@ -80,13 +80,28 @@
<td>-</td> <td>-</td>
</tr> </tr>
<tr> <tr>
<td>expandedWidth <sup>2.8.14+</sup></td> <td>expandedWidth <sup>2.8.15+</sup></td>
<td> <td>
设置单元格被展开后的宽度,默认取表格容器的三分之一宽度。若设置的值的小于当前列宽,则展开后的列宽保持不变。 设置单元格被展开后的宽度。若设置的值的小于当前列宽,则展开后的列宽保持不变。注:当 `expandedMode` 属性为默认值时有效。
</td> </td>
<td>number</td> <td>number</td>
<td>-</td>
</tr>
<tr>
<td>expandedMode <sup>2.8.17+</sup></td>
<td>
用于设置所有单元格默认展开方式,可选值有:
- `tips` 悬浮展开方式
- `default` 多行展开方式(默认)
优先级高于 `cellExpandedMode` 基础属性
</td>
<td>string</td>
<td>-</td> <td>-</td>
</tr> </tr>
<tr> <tr>
@ -467,4 +482,4 @@ edit: function(d){
</td> </td>
</tr> </tr>
</tbody> </tbody>
</table> </table>

View File

@ -188,6 +188,33 @@
<td>-</td> <td>-</td>
</tr> </tr>
<tr> <tr>
<td>cellExpandedMode <sup>2.8.17+</sup></td>
<td>
用于设置所有单元格默认展开方式,可选值有:
- `tips` 悬浮展开方式
- `default` 多行展开方式(默认)
</td>
<td>string</td>
<td>-</td>
</tr>
<tr>
<td>cellExpandedWidth <sup>2.8.17+</sup></td>
<td>
用于设置所有单元格默认展开后的宽度。当 `cellExpandedMode` 属性为默认值时有效。
</td>
<td>number</td>
<td>
`60`
</td>
</tr>
<tr>
<td>escape <sup>2.6+</sup></td> <td>escape <sup>2.6+</sup></td>
<td>是否开启对内容的编码(转义 html</td> <td>是否开启对内容的编码(转义 html</td>
<td>boolean</td> <td>boolean</td>
@ -390,10 +417,28 @@ initSort: {
</td> </td>
</tr> </tr>
<tr> <tr>
<td>before <sup>2.7+</sup></td> <td>
<td>数据渲染之前的回调函数。</td>
<td>function</td> [before](#options.before) <sup>2.7+</sup>
<td>-</td>
</td>
<td colspan="3">
<div class="ws-anchor" id="options.before">
数据渲染之前的回调函数。
</div>
```
table.render({
before: function(options){
console.log(options); // 当前实例属性配置项
options.where.abc = 123; // 修改或额外追加 where 属性
},
// … // 其它属性
});
```
</td>
</tr> </tr>
<tr> <tr>
<td> <td>
@ -401,7 +446,7 @@ initSort: {
[done](#options.done) [done](#options.done)
</td> </td>
<td> <td colspan="3">
<div class="ws-anchor" id="options.done"> <div class="ws-anchor" id="options.done">
数据渲染完毕的回调函数。返回的参数如下: 数据渲染完毕的回调函数。返回的参数如下:
@ -414,20 +459,26 @@ table.render({
console.log(curr); // 得到当前页码 console.log(curr); // 得到当前页码
console.log(count); // 得到数据总量 console.log(count); // 得到数据总量
console.log(origin); // 回调函数所执行的来源 --- 2.8.7+ console.log(origin); // 回调函数所执行的来源 --- 2.8.7+
} },
// … // 其它属性 // … // 其它属性
}); });
``` ```
</td> </td>
<td>function</td>
<td>-</td>
</tr> </tr>
<tr> <tr>
<td>error <sup>2.6+</sup></td> <td>error <sup>2.6+</sup></td>
<td> 数据请求失败的回调函数。返回两个参数:错误对象、内容。</td> <td colspan="3">
<td>function</td>
<td>-</td> 数据请求失败的回调函数。返回两个参数:错误对象、内容。
```
error: function(e, msg) {
console.log(e, msg)
}
```
</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>

View File

@ -55,7 +55,7 @@ layui.use(['table', 'dropdown'], function(){
// 创建渲染实例 // 创建渲染实例
table.render({ table.render({
elem: '#test', elem: '#test',
url:'/static/2.8/json/table/demo1.json', // 此处为静态模拟数据,实际使用时需换成真实接口 url: '/static/2.8/json/table/demo1.json', // 此处为静态模拟数据,实际使用时需换成真实接口
toolbar: '#toolbarDemo', toolbar: '#toolbarDemo',
defaultToolbar: ['filter', 'exports', 'print', { defaultToolbar: ['filter', 'exports', 'print', {
title: '提示', title: '提示',
@ -73,7 +73,7 @@ layui.use(['table', 'dropdown'], function(){
{type: 'checkbox', fixed: 'left'}, {type: 'checkbox', fixed: 'left'},
{field:'id', fixed: 'left', width:80, title: 'ID', sort: true, totalRowText: '合计:'}, {field:'id', fixed: 'left', width:80, title: 'ID', sort: true, totalRowText: '合计:'},
{field:'username', width:80, title: '用户'}, {field:'username', width:80, title: '用户'},
{field:'email', title:'邮箱 <i class="layui-icon layui-icon-tips layui-font-14" lay-event="email-tips" title="该字段开启了编辑功能" style="margin-left: 5px;"></i>', fieldTitle: '邮箱', hide: 0, width:150, edit: 'text'}, {field:'email', title:'邮箱 <i class="layui-icon layui-icon-tips layui-font-14" lay-event="email-tips" title="该字段开启了编辑功能" style="margin-left: 5px;"></i>', fieldTitle: '邮箱', hide: 0, width:150, expandedMode: 'tips', edit: 'text'},
{field:'sex', width:80, title: '性别', sort: true}, {field:'sex', width:80, title: '性别', sort: true},
{field:'sign', title: '签名', edit: 'textarea', minWidth: 260, expandedWidth: 260, totalRow: '{{!人物:<span class="layui-badge-rim">唐代:{{= d.TOTAL_ROW.era.tang }} </span> <span class="layui-badge-rim">宋代:{{= d.TOTAL_ROW.era.song }}</span> <span class="layui-badge-rim">现代:{{= d.TOTAL_ROW.era.xian }}</span>!}}'}, {field:'sign', title: '签名', edit: 'textarea', minWidth: 260, expandedWidth: 260, totalRow: '{{!人物:<span class="layui-badge-rim">唐代:{{= d.TOTAL_ROW.era.tang }} </span> <span class="layui-badge-rim">宋代:{{= d.TOTAL_ROW.era.song }}</span> <span class="layui-badge-rim">现代:{{= d.TOTAL_ROW.era.xian }}</span>!}}'},
{field:'experience', width: 100, title: '积分', sort: true, totalRow: '{{!{{= d.TOTAL_NUMS }} 😊!}}'}, {field:'experience', width: 100, title: '积分', sort: true, totalRow: '{{!{{= d.TOTAL_NUMS }} 😊!}}'},

View File

@ -11,6 +11,8 @@ toc: true
以下所有示例中演示的数据均为「静态模拟数据」,实际使用时换成您的真实接口即可。 以下所有示例中演示的数据均为「静态模拟数据」,实际使用时换成您的真实接口即可。
<div class="ws-docs-showcase"></div>
<div> <div>
{{- d.include("/table/detail/demo.md") }} {{- d.include("/table/detail/demo.md") }}
</div> </div>

View File

@ -90,6 +90,16 @@ data: {
</td> </td>
<td>object</td> <td>object</td>
<td>-</td>
</tr>
<tr>
<td>dataType <sup>2.8.17+</sup></td>
<td>
服务端返回的数据类型,如:`text,json,xml` 等
</td>
<td>string</td>
<td>-</td> <td>-</td>
</tr> </tr>
<tr> <tr>
@ -470,4 +480,4 @@ error: function(index, upload){
</td> </td>
</tr> </tr>
</tbody> </tbody>
</table> </table>

View File

@ -11,6 +11,8 @@ toc: true
以下示例的部分上传接口由第三方网站 `https://httpbin.org` 提供,它可以模拟各类 HTTP 请求。若未配置上传接口的,每次上传都会报「请求上传接口出现异常」的提示,这属于正常现象。 以下示例的部分上传接口由第三方网站 `https://httpbin.org` 提供,它可以模拟各类 HTTP 请求。若未配置上传接口的,每次上传都会报「请求上传接口出现异常」的提示,这属于正常现象。
<div class="ws-docs-showcase"></div>
<div> <div>
{{- d.include("/upload/detail/demo.md") }} {{- d.include("/upload/detail/demo.md") }}
</div> </div>
@ -122,4 +124,4 @@ inst.reload({
- 自建上传服务。在服务端配置 `CORS` 开启跨资源共享。 即对接口所在的服务器设置 `Access-Control-Allow-Origin ` 相关 `header` 信息。 - 自建上传服务。在服务端配置 `CORS` 开启跨资源共享。 即对接口所在的服务器设置 `Access-Control-Allow-Origin ` 相关 `header` 信息。
- 第三方上传服务。如:阿里云、腾讯云等,只需按照不同平台对应的上传 SDK 进行操作即可。 - 第三方上传服务。如:阿里云、腾讯云等,只需按照不同平台对应的上传 SDK 进行操作即可。

View File

@ -11,6 +11,43 @@ toc: true
> 导读:📑 [Layui 2.8 《升级指南》](/notes/2.8/upgrade-guide.html) · 📑 [Layui 新版文档站上线初衷](/notes/2.8/news.html) > 导读:📑 [Layui 2.8 《升级指南》](/notes/2.8/upgrade-guide.html) · 📑 [Layui 新版文档站上线初衷](/notes/2.8/news.html)
<h2 id="2.8.17" class="ws-anchor">
2.8.17
<span class="layui-badge-rim">2023-09-11</span>
</h2>
- #### table
- 新增 `cellExpandedMode` 基础属性,用于设置所有单元格默认展开方式 # I7XW28 [8bd8415]
- 新增 `cellExpandedWidth` 基础属性,用于设置所有单元格默认展开后的宽度 [8bd8415]
- 新增 `expandedMode` 表头属性,用于设置当前表头单元格展开方式,优先级高于 `cellExpandedMode` [8bd8415]
- 修复 导出来自 treeTable 数据的顺序错乱问题 # I7YOXZ [3123adf]
- #### form
- 优化 验证机制,以确保自定义验证规则的灵活性,内置规则若为必填项,依旧需叠加 `required` 规则 [a00ecf2]
- 剔除 `verIncludeRequired` 全局属性,因为会造成不必要的歧义 [a00ecf2]
- #### laydate
- 修复 开启 `rangeLinked` 属性后done 函数第二个参数未能正确返回开始日期的问题 #I7XBOA/I7YCHW [4d9365e]
- 修复 开启 `rangeLinked``range` 为数组时,当初始值格式不符而自动校正导致的开始日期表单赋值异常问题 [4d9365e]
- #### upload
- 新增 `dataType` 属性,用于定义服务端返回的数据类型 [58e675c]
- 优化 多文件模式中,正在上传中的文件会被再次触发上传的问题 # I7XXTW/I4C6XE [9a6b85f]
- #### code
- 重构 主体结构,以更好地适配第三方语法高亮库 # 1352 [ad5935c]
- 新增 实例返回的对象,包含对当前实例进行重载等方法成员 [ad5935c]
- 新增 `codeRender` 函数,用于重新渲染 code譬如代码高亮处理 # 1352
- 新增 `highlighter` 属性,用于指定语法高亮器,支持 `hljs,prism,shiki` 等流行库 # 1352
- 新增 `lang` 属性,用于指定语言类型 # 1352
- 新增 `langMarker` 属性,用于是否在代码域右上角显示语言类型 # 1352
- 新增 `wordWrap` 属性,用于设置文字是否自动换行 [ad5935c]
- 加强 `tools` 属性,进一步提升可扩展性 [ad5935c]
- 优化 `dark` 模式主题,与 vscode 保持一致 [ad5935c]
- #### lay
- 新增 `lay.clipboard.writeText(options)` 方法,用于写入剪切板(复制) [5a00d0a]
- #### 公共类
- 新增 `layui-padding-*``layui-margin-*` 内外边距样式类名 [5e0d71d]
### 下载: [layui-v2.8.17.zip](https://gitee.com/layui/layui/attach_files/1523966/download)
---
<h2 id="2.8.16" class="ws-anchor"> <h2 id="2.8.16" class="ws-anchor">
2.8.16 2.8.16
@ -31,7 +68,7 @@ toc: true
- 修复 `data` 模式下排序之后出现节点结构错乱的问题 # 1358/I7TXXL - 修复 `data` 模式下排序之后出现节点结构错乱的问题 # 1358/I7TXXL
- 优化 `data.cascade` 属性,新增 `none` 可选值,即操作节点时不做任何联动 # 1358 - 优化 `data.cascade` 属性,新增 `none` 可选值,即操作节点时不做任何联动 # 1358
- 优化 数据项为禁用状态时的全选复选框的状态 # 1329 - 优化 数据项为禁用状态时的全选复选框的状态 # 1329
- 优化 异步加载节点为空时的展开状态 # 1326 - 优化 异步加载节点为空时的展开状态 # 1326
- #### laydate - #### laydate
- 优化 `shortcuts.value` 快捷选项的赋值属性,支持函数类型 # 1324 - 优化 `shortcuts.value` 快捷选项的赋值属性,支持函数类型 # 1324
- #### rate - #### rate

View File

@ -8,32 +8,67 @@
<link href="../src/css/layui.css" rel="stylesheet"> <link href="../src/css/layui.css" rel="stylesheet">
<style> <style>
body{padding: 32px;} body{padding: 32px;}
pre{margin-bottom: 20px;} pre{margin: 16px 0;}
</style> </style>
</head> </head>
<body> <body>
<pre class="layui-code" lay-height="300px"> <pre id="test" class="layui-test">
// 在里面存放任意的文本内容 <textarea class="layui-hide">
code line <div class="layui-btn-container">
code line <button type="button" class="layui-btn">默认按钮</button>
code line </div>
code line
code line <p class="layui-padding-3">
code line AaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaA
code line </p>
code line
code line <div class="layui-btn-container">
code line <button class="layui-btn layui-btn-primary layui-border-green">主色按钮</button>
code line </div>
code line <script type="text/html">
code line <h3>{{= d.title }}</h3>
code line <ul>
code line {{# layui.each(d.list, function(index, item){ }}
code line <li>
code line <span>{{= item.modname }}</span>
<span>{{= item.alias }}</span>
<span>{{= item.site || '' }}</span>
</li>
{{# }); }}
<p>{{# if(d.list.length === 0){ }}
无数据
{{# } }}</p>
</ul>
</script>
<script>
layui.use(function () {
var layer = layui.layer;
const a = '1'
function aa(a, b) {
return '11'
}
layer.msg(layui.v)
})
</script>
</textarea>
</pre> </pre>
<pre><code class="layui-code" lay-options="{header: true}">
code line
code line
code line
</code></pre>
<pre class="layui-code" lay-options="{style: 'height: 300px'}" id="ID-multi-line"></pre>
<script type="module">
// 生成批量行,测试行结构
const elem = document.getElementById('ID-multi-line');
elem.innerHTML = Array(1001).fill().map(v => {
return Math.random().toString(32).substring(2).toUpperCase();
}).join('\n');
</script>
<pre class="layui-code" lay-options="{title: '不显示行号', ln: false}"> <pre class="layui-code" lay-options="{title: '不显示行号', ln: false}">
code line code line
code line code line
@ -101,33 +136,137 @@ code line
</div> </div>
</pre> </pre>
<pre class="layui-code" lay-about="code"> <pre class="layui-code" lay-options="{about: 'About info'}">
About About
</pre> </pre>
<pre id="custom1">
custom more about
</pre>
<script src="../src/layui.js"></script> <script src="../src/layui.js"></script>
<script src="https://cdn.staticfile.org/highlight.js/11.8.0/highlight.min.js"></script>
<script src="https://cdn.staticfile.org/prism/1.29.0/prism.min.js"></script>
<script> <script>
layui.use('code', function(){ layui.use(['code', 'dropdown'], function(){
// 通用实例,根据元素属性定制化参数 var dropdown = layui.dropdown;
layui.code({ var $ = layui.$;
//about: 'code' // 右上角默认显示 code
tools: ['tips'], // return;
preview: true
// 高亮主题 css 库
var themeData = $.map([
// hljs 主题库
'https://cdn.staticfile.org/highlight.js/11.8.0/styles/vs2015.min.css',
'https://cdn.staticfile.org/highlight.js/11.8.0/styles/vs.min.css',
'https://cdn.staticfile.org/highlight.js/11.8.0/styles/github-dark.min.css',
'https://cdn.staticfile.org/highlight.js/11.8.0/styles/github.min.css',
'https://cdn.staticfile.org/highlight.js/11.8.0/styles/base16/google-dark.min.css',
'https://cdn.staticfile.org/highlight.js/11.8.0/styles/base16/google-light.min.css',
'https://cdn.staticfile.org/highlight.js/11.8.0/styles/monokai-sublime.min.css',
'-',
// prism 主题库
'https://cdn.staticfile.org/prism/1.29.0/themes/prism-dark.min.css',
'https://cdn.staticfile.org/prism/1.29.0/themes/prism.min.css'
], function(v, index) {
return {
title: v,
link: v,
highlighter: v.indexOf('prism') === -1 ? 'hljs' : 'prism',
type: v === '-' ? '-' : 'normal'
};
}); });
// custom more about var codeInst = layui.code({
elem: '#test',
preview: true,
codeStyle: 'height: 510px;',
previewStyle: 'word-wrap: break-word;',
// theme: 'dark',
// header: true,
// wordWrap: false, // 是否自动换行
lang: 'html',
highlighter: "hljs",
/*codeRender: function (code, opts) {
layui.link(themeData[1].link, 'layui-code-theme');
return hljs.highlight(code, {language: opts.lang}).value;
},*/
tools: [
'full',
{
title: ['文字换行'],
type: 'form',
event: function(obj) {
dropdown.render({
elem: obj.elem,
data: [{title: '自动换行', wordWrap: true}, {title: '不自动换行', wordWrap: false}],
show: true,
click: function(data, othis) {
codeInst.reload({
wordWrap: data.wordWrap
});
}
});
}
},
{
title: ['切换高亮主题'],
type: 'theme',
event: function(obj) {
dropdown.render({
elem: obj.elem,
data: themeData,
show: true,
click: function(data, othis) {
$('#layuicss-layui-code-theme').remove();
layui.link(data.link, 'layui-code-theme');
// 若高亮器有变化,则重载
if (data.highlighter !== codeInst.config.highlighter) {
var highlighter = {
hljs: function(code, opts) {
return hljs.highlight(code, {
language: opts.lang
}).value;
},
prism: function(code, opts) {
return Prism.highlight(
code,
Prism.languages[opts.lang],
opts.lang
);
}
};
// 重载
codeInst.reload({
highlighter: data.highlighter,
codeRender: function (code, opts) {
return highlighter[data.highlighter](code, opts);
}
});
}
}
});
}
}
]
});
// 仅重载 code
layui.debounce(function() {
codeInst.reloadCode({
codeRender: function(code, opts) {
layui.link(themeData[1].link, 'layui-code-theme');
return hljs.highlight(code, {language: opts.lang}).value;
}
});
}, 300)();
// 通用实例,根据元素属性定制化参数
layui.code({ layui.code({
elem: '#custom1', elem: '.layui-code',
about: [ tools: ['tips'],
'<a href="javascript:;">复制</a>', langMarker: true,
'<a href="about:blank" target="_blank">跳转</a>' lang: 'html',
].join('') // preview: true
}) });
}); });
</script> </script>
</body> </body>

View File

@ -170,7 +170,7 @@
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">邮箱</label> <label class="layui-form-label">邮箱</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input type="email" name="email" lay-verify="email" lay-verType="alert" autocomplete="off" class="layui-input"> <input type="email" name="email" lay-verify="email" lay-vertype="alert" autocomplete="off" class="layui-input">
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
@ -200,7 +200,7 @@
<div class="layui-inline"> <div class="layui-inline">
<label class="layui-form-label">行内表单</label> <label class="layui-form-label">行内表单</label>
<div class="layui-input-block"> <div class="layui-input-block">
<select name="quiz" lay-verify="required" lay-verType="tips" lay-filter="quiz111"> <select name="quiz" lay-verify="required" lay-vertype="tips" lay-filter="quiz111">
<option value="">请"选择"问题</option> <option value="">请"选择"问题</option>
<option value="0">你工"作"的 第一个城市</option> <option value="0">你工"作"的 第一个城市</option>
<option value="1" disabled>你的工号</option> <option value="1" disabled>你的工号</option>
@ -380,19 +380,23 @@
var util = layui.util; var util = layui.util;
var laydate = layui.laydate; var laydate = layui.laydate;
//自定义验证规则 // 自定义验证规则
form.verify({ form.verify({
title: function(value){ title: function(value){
if(value.length < 5){ if(value && value.length < 5){ //
return '标题也太短了吧'; return '标题也太短了吧';
} }
},
pass: function(value) {
if (!/(.+){6,12}$/.test(value)) {
return '密码必须 6 到 12 位';
}
},
amount: function(value) {
if (value && !/^\d+\.\b\d{2}\b$/.test(value)) { // 值若填写时才校验
return '金额必须为小数保留两位';
}
} }
,pass: [/(.+){6,12}$/, '密码必须6到12位']
,money: [
/^\d+\.\b\d{2}\b$/
,'金额必须为小数保留两位'
]
//,n: [/^(\d)+$/, '数字校验']
}); });
/* /*

View File

@ -5,6 +5,7 @@
,"totalRow": { ,"totalRow": {
"checkin": "777" "checkin": "777"
} }
,"data1": []
,"data": [{ ,"data": [{
"id": "10001" "id": "10001"
,"username": "杜甫123" ,"username": "杜甫123"
@ -129,4 +130,4 @@
,"checkin": "106" ,"checkin": "106"
,"joinTime": "2016-10-14" ,"joinTime": "2016-10-14"
}] }]
} }

View File

@ -174,38 +174,44 @@ layui.use('laydate', function(laydate){
}); });
//范围选择1 // 范围选择1
laydate.render({ laydate.render({
elem: '#test1' //指定元素 elem: '#test1', // 指定元素
,type: 'datetime' type: 'datetime',
,trigger: 'click' trigger: 'click',
//,lang: 'en' // lang: 'en',
//,theme: 'grid' // theme: 'grid',
,range: true //开启日期范围,默认使用“-”分割 range: true, // 开启日期范围,默认使用“-”分割
//,min: '1970-1-1' // rangeLinked: true,
//,max: '2021-5-9' // min: '1970-1-1',
//,value: '2021-05-09 12:06:09' // max: '2021-5-9',
//,value: '2021-05-08 - 2021-03-27' // value: '2021-05-09 12:06:09',
,done: function(value, date, endDate){ // value: '2021-05-08 - 2021-03-27',
done: function(value, date, endDate){
console.log(value, date, endDate); console.log(value, date, endDate);
//this.elem.val(123); //this.elem.val(123);
} },
,change: function(value, date, endDate){ change: function(value, date, endDate){
console.log(value, date, endDate); console.log(value, date, endDate);
} }
}); });
//return; // return;
//范围选择2 // 范围选择2
laydate.render({ laydate.render({
elem: '#test1-2' elem: '#test1-2',
,type: 'date' type: 'date',
,range: ['#test-startDate-1', '#test-endDate-1'] range: ['#test-startDate-1', '#test-endDate-1'],
,rangeLinked: true // 是否开启日期范围选择时的区间联动标注模式 rangeLinked: true, // 是否开启日期范围选择时的区间联动标注模式
//,value: ['2022-05-01', '2022-06-01'] // value: ['2022-05-01', '2022-10-01'],
//,value: '2022-05-01 - 2022-06-01' // value: '2022-05-01 - 2022-06-01',
done: function (value, date, endDate) {
console.log(value);
console.log(date);
console.log(endDate);
}
}); });

View File

@ -31,6 +31,8 @@
重载测试 重载测试
<i class="layui-icon layui-icon-down layui-font-12"></i> <i class="layui-icon layui-icon-down layui-font-12"></i>
</button> </button>
<button class="layui-btn layui-btn-sm layui-btn-primary" lay-event="multi-row"> 多行 </button>
<button class="layui-btn layui-btn-sm layui-btn-primary" lay-event="default-row"> 单行 </button>
<button class="layui-btn layui-btn-sm" id="moreTest"> <button class="layui-btn layui-btn-sm" id="moreTest">
更多测试 更多测试
<i class="layui-icon layui-icon-down layui-font-12"></i> <i class="layui-icon layui-icon-down layui-font-12"></i>
@ -75,12 +77,12 @@
<table id="test"></table> <table id="test"></table>
<script src="../src/layui.js" src1="https://cdn.staticfile.org/layui/2.7.6/layui.js"></script> <script src="../src/layui.js"></script>
<script> <script>
(function(off){ (function(off){
if(!off) return; if(!off) return;
layui.disuse('table').extend({ layui.disuse('table').extend({
table: '{/}//ww:5018/layui/2.6.13/src/modules/table' table: '{/}https://cdn.staticfile.org/layui/2.7.6/layui.js'
}); });
})(); })();
@ -116,7 +118,7 @@ layui.use(['table', 'dropdown'], function(){
// height: 300 // height: 300
}); });
//渲染 // 渲染
window.ins1 = table.render({ window.ins1 = table.render({
elem: '#test', elem: '#test',
height: 520, height: 520,
@ -153,15 +155,17 @@ layui.use(['table', 'dropdown'], function(){
// escape: false, // escape: false,
editTrigger: 'dblclick', editTrigger: 'dblclick',
// cellMaxWidth: 320 // cellMaxWidth: 320
// cellExpandedWidth: 160, // 单元格默认展开后的宽度
// cellExpandedStyle: 'tips', // 单元格默认展开风格
cols: !1 ? test_cols : [[ cols: !1 ? test_cols : [[
{type: 'checkbox', fixed: 'left'}, {type: 'checkbox', fixed: 'left'},
//,{type: 'numbers', fixed: 'left'} // {type: 'numbers', fixed: 'left'},
{field:'id', title:'ID', width:80, fixed: 'left', unresize: true, sort: true, totalRowText: '合计:'}, {field:'id', title:'ID', width:80, fixed: 'left', unresize: true, sort: true, totalRowText: '合计:'},
{field:'username', title:'用户名 <i class="layui-icon layui-icon-username" lay-event="username"></i>', width:120, edit: function(d){ {field:'username', expandedStyle: 'tips', title:'用户名 <i class="layui-icon layui-icon-username" lay-event="username"></i>', width:120, edit: function(d){
return !d.LAY_DISABLED; return !d.LAY_DISABLED;
}, templet: '#usernameTpl'}, }, templet: '#usernameTpl'},
{field:'xxx', title:'测试', edit: 'text'}, {field:'xxx', title:'测试', edit: 'text'},
{field:'email', minWidth: 160, maxWidth: 320, title:'邮箱 <i class="layui-icon layui-icon-email" lay-event="email"></i>', fieldTitle: '邮箱', hide: 0, edit: 'text', templet: function(d){ {field:'email', minWidth: 160, maxWidth: 320, title:'邮箱 <i class="layui-icon layui-icon-email" lay-event="email"></i>', fieldTitle: '邮箱', hide: 0, edit: 'text', style: 'background-color: #fafafa; color: red;', templet: function(d){
return '<em>'+ layui.util.escape(d.email) +'</em>' return '<em>'+ layui.util.escape(d.email) +'</em>'
}}, }},
{field:'sex', title:'性别', width:80, edit: 'text', sort: true, escape: false}, {field:'sex', title:'性别', width:80, edit: 'text', sort: true, escape: false},
@ -171,7 +175,7 @@ layui.use(['table', 'dropdown'], function(){
var td = obj.td(this.field); //获取当前 td var td = obj.td(this.field); //获取当前 td
return td.find('select').val(); return td.find('select').val();
}}, }},
{field:'sign', title:'签名', minWidth: 200, expandedWidth: 350, style:'color: #5FB878', edit: 'textarea'}, {field:'sign', title:'签名', minWidth: 200, style:'color: #5FB878', edit: 'textarea'},
{field: 'experience', title: '积分', width: 100, sort: true, align:'center', totalRow: !1 ? true : '{{= d.TOTAL_NUMS }} 分 😊', templet: '<div><a href="" class="layui-table-link">{{= d[d.LAY_COL.field] }}</a></div>'}, {field: 'experience', title: '积分', width: 100, sort: true, align:'center', totalRow: !1 ? true : '{{= d.TOTAL_NUMS }} 分 😊', templet: '<div><a href="" class="layui-table-link">{{= d[d.LAY_COL.field] }}</a></div>'},
{field:'ip', title:'IP', width: 120, align: 'right'}, {field:'ip', title:'IP', width: 120, align: 'right'},
{field:'checkin', title:'打卡', width: 100, sort: true, totalRow: '{{= d.TOTAL_ROW.checkin }} 次'}, {field:'checkin', title:'打卡', width: 100, sort: true, totalRow: '{{= d.TOTAL_ROW.checkin }} 次'},
@ -256,7 +260,7 @@ layui.use(['table', 'dropdown'], function(){
// 重载测试 // 重载测试
dropdown.render({ dropdown.render({
elem: '#reloadTest', //可绑定在任意元素中,此处以上述按钮为例 elem: '#reloadTest', // 可绑定在任意元素中,此处以上述按钮为例
data: [{ data: [{
id: 'reload', id: 'reload',
title: '重载' title: '重载'
@ -336,10 +340,9 @@ layui.use(['table', 'dropdown'], function(){
} }
}); });
// 更多测试 // 更多测试
dropdown.render({ dropdown.render({
elem: '#moreTest', //可绑定在任意元素中,此处以上述按钮为例 elem: '#moreTest', // 可绑定在任意元素中,此处以上述按钮为例
data: [{ data: [{
id: 'add', id: 'add',
title: '添加' title: '添加'
@ -385,8 +388,8 @@ layui.use(['table', 'dropdown'], function(){
/* /*
request: { // 自定义请求参数名称 request: { // 自定义请求参数名称
pageName: 'curr', //页码的参数名称默认page pageName: 'curr', // 页码的参数名称默认page
limitName: 'nums' //每页数据量的参数名默认limit limitName: 'nums' // 每页数据量的参数名默认limit
}, },
parseData: function(res){ // 任意数据格式的解析 parseData: function(res){ // 任意数据格式的解析
return { return {
@ -403,20 +406,20 @@ layui.use(['table', 'dropdown'], function(){
} }
}); });
//排序事件 // 排序事件
table.on('sort(test)', function(obj){ table.on('sort(test)', function(obj){
//console.log(obj); // console.log(obj);
//return; // return;
layer.msg('服务端排序。order by '+ obj.field + ' ' + obj.type); layer.msg('服务端排序。order by '+ obj.field + ' ' + obj.type);
//服务端排序 // 服务端排序
table.reloadData('test', { table.reloadData('test', {
//initSort: obj, // initSort: obj,
//page: {curr: 1}, //重新从第一页开始 // page: {curr: 1}, // 重新从第一页开始
where: { // 向服务端传入排序参数 where: { // 向服务端传入排序参数
key: obj.field, //排序字段 key: obj.field, // 排序字段
order: obj.type //排序方式 order: obj.type // 排序方式
} }
}); });
}); });
@ -430,18 +433,31 @@ layui.use(['table', 'dropdown'], function(){
case 'getCheckData': case 'getCheckData':
var data = checkStatus.data; var data = checkStatus.data;
layer.alert(layui.util.escape(JSON.stringify(data))); layer.alert(layui.util.escape(JSON.stringify(data)));
break; break;
case 'getData': case 'getData':
var getData = table.getData(id); var getData = table.getData(id);
console.log(getData); console.log(getData);
layer.alert(layui.util.escape(JSON.stringify(getData))); layer.alert(layui.util.escape(JSON.stringify(getData)));
break; break;
case 'isAll': case 'isAll':
layer.msg(checkStatus.isAll ? '全选': '未全选') layer.msg(checkStatus.isAll ? '全选': '未全选')
break; break;
case 'multi-row':
table.reload('test', {
// 设置行样式,此处以设置多行高度为例。若为单行,则没必要设置改参数 - 注v2.7.0 新增
lineStyle: 'height: 95px;'
});
layer.msg('即通过设置 lineStyle 参数可开启多行');
break;
case 'default-row':
table.reload('test', {
lineStyle: null // 恢复单行
});
layer.msg('已设为单行');
break;
case 'LAYTABLE_TIPS': case 'LAYTABLE_TIPS':
layer.alert('Table for layui-v'+ layui.v); layer.alert('Table for layui-v'+ layui.v);
break; break;
}; };
}); });
@ -450,16 +466,11 @@ layui.use(['table', 'dropdown'], function(){
console.log(obj); console.log(obj);
}); });
//触发单元格工具事件 // 触发单元格工具事件
table.on('tool(test)', function(obj){ // 双击 toolDouble table.on('tool(test)', function(obj){ // 双击 toolDouble
var data = obj.data; var data = obj.data;
//console.log(obj) // console.log(obj)
if(obj.event === 'del'){ if (obj.event === 'edit') {
layer.confirm('真的删除行么', function(index){
obj.del();
layer.close(index);
});
} else if(obj.event === 'edit'){
layer.prompt({ layer.prompt({
formType: 2 formType: 2
,value: data.email ,value: data.email
@ -477,17 +488,20 @@ layui.use(['table', 'dropdown'], function(){
*/ */
layer.close(index); layer.close(index);
}); });
} else if (obj.event === 'del') {
layer.confirm('真的删除行么', function(index){
obj.del();
layer.close(index);
});
} }
}); });
// 触发表格复选框选择
//触发表格复选框选择
table.on('checkbox(test)', function(obj){ table.on('checkbox(test)', function(obj){
console.log(obj) console.log(obj)
}); });
//触发表格单选框选择 // 触发表格单选框选择
table.on('radio(test)', function(obj){ table.on('radio(test)', function(obj){
console.log(obj) console.log(obj)
}); });

View File

@ -13,6 +13,12 @@
<table class="layui-hide" id="test"></table> <table class="layui-hide" id="test"></table>
<script type="text/html" id="TPL-treeTable-demo">
<div class="layui-btn-container">
<button class="layui-btn layui-btn-sm" lay-event="getChecked">获取选中数据</button>
</div>
</script>
<script src="../src/layui.js"></script> <script src="../src/layui.js"></script>
<script> <script>
layui.use(['treeTable'], function(){ layui.use(['treeTable'], function(){
@ -23,6 +29,7 @@ layui.use(['treeTable'], function(){
elem: '#test', elem: '#test',
url: './json/treeTable/demo-1.json', url: './json/treeTable/demo-1.json',
maxHeight: 'full-32', maxHeight: 'full-32',
toolbar: '#TPL-treeTable-demo',
tree: { tree: {
customName: { customName: {
name: 'name' name: 'name'

View File

@ -191,10 +191,10 @@ layui.use(['upload', 'element'], function(){
url: 'https://httpbin.org/post', url: 'https://httpbin.org/post',
accept: 'file', accept: 'file',
multiple: true, multiple: true,
number: 3, number: 5,
auto: false, auto: false,
bindAction: '#testListAction', bindAction: '#testListAction',
size: 30, // size: 30,
choose: function(obj){ choose: function(obj){
var files = this.files = obj.pushFile(); // 将每次选择的文件追加到文件队列 var files = this.files = obj.pushFile(); // 将每次选择的文件追加到文件队列
//读取本地文件 //读取本地文件

View File

@ -1,6 +1,6 @@
{ {
"name": "layui", "name": "layui",
"version": "2.8.16", "version": "2.8.17",
"description": "Classic modular Front-End UI library", "description": "Classic modular Front-End UI library",
"main": "dist/layui.js", "main": "dist/layui.js",
"license": "MIT", "license": "MIT",

View File

@ -513,12 +513,37 @@ a cite{font-style: normal; *cursor:pointer;}
.layui-col-space32>*{padding: 16px;} .layui-col-space32>*{padding: 16px;}
/** 页面元素 **/ /* 内边距 */
.layui-btn, .layui-input, .layui-textarea, .layui-upload-button, .layui-select{outline: none; -webkit-appearance: none; transition: all .3s; -webkit-transition: all .3s; box-sizing: border-box;} .layui-padding-1{padding: 4px !important;}
.layui-padding-2{padding: 8px !important;}
.layui-padding-3{padding: 16px !important;}
.layui-padding-4{padding: 32px !important;}
.layui-padding-5{padding: 48px !important;}
/* 引用 */.layui-elem-quote{margin-bottom: 10px; padding: 15px; line-height: 1.8; border-left: 5px solid #16b777; border-radius: 0 2px 2px 0; background-color: #fafafa;} /* 外边距 */
.layui-margin-1{margin: 4px !important;}
.layui-margin-2{margin: 8px !important;}
.layui-margin-3{margin: 16px !important;}
.layui-margin-4{margin: 32px !important;}
.layui-margin-5{margin: 48px !important;}
/*
*
*/
.layui-btn,
.layui-input,
.layui-select,
.layui-textarea,
.layui-upload-button{outline: none; -webkit-appearance: none; transition: all .3s; -webkit-transition: all .3s; box-sizing: border-box;}
/* 引用 */
.layui-elem-quote{margin-bottom: 10px; padding: 15px; line-height: 1.8; border-left: 5px solid #16b777; border-radius: 0 2px 2px 0; background-color: #fafafa;}
.layui-quote-nm{border-style: solid; border-width: 1px; border-left-width: 5px; background: none;} .layui-quote-nm{border-style: solid; border-width: 1px; border-left-width: 5px; background: none;}
/* 字段集合 */.layui-elem-field{margin-bottom: 10px; padding: 0; border-width: 1px; border-style: solid;}
/* 字段集合 */
.layui-elem-field{margin-bottom: 10px; padding: 0; border-width: 1px; border-style: solid;}
.layui-elem-field legend{margin-left: 20px; padding: 0 10px; font-size: 20px;} .layui-elem-field legend{margin-left: 20px; padding: 0 10px; font-size: 20px;}
.layui-field-title{margin: 16px 0; border-width: 0; border-top-width: 1px;} .layui-field-title{margin: 16px 0; border-width: 0; border-top-width: 1px;}
.layui-field-box{padding: 15px;} .layui-field-box{padding: 15px;}
@ -534,10 +559,8 @@ a cite{font-style: normal; *cursor:pointer;}
/* /*
*
*/
*/
/* 折叠面板 */ /* 折叠面板 */
@ -642,9 +665,9 @@ a cite{font-style: normal; *cursor:pointer;}
.layui-text a:not(.layui-btn){color: #01AAED;} .layui-text a:not(.layui-btn){color: #01AAED;}
.layui-text a:not(.layui-btn):hover{text-decoration: underline;} .layui-text a:not(.layui-btn):hover{text-decoration: underline;}
.layui-text blockquote:not(.layui-elem-quote){padding: 5px 15px; border-left: 5px solid #eee;} .layui-text blockquote:not(.layui-elem-quote){padding: 5px 15px; border-left: 5px solid #eee;}
.layui-text pre > code:not(.layui-code){padding: 15px; font-family: Courier New,Lucida Console,Consolas; background-color: #fafafa;} .layui-text pre > code:not(.layui-code){padding: 15px; font-family: "Courier New",Consolas,"Lucida Console";}
/* 字体大小及颜色 */ /* 字体大小 */
.layui-font-12{font-size: 12px !important;} .layui-font-12{font-size: 12px !important;}
.layui-font-13{font-size: 13px !important;} .layui-font-13{font-size: 13px !important;}
.layui-font-14{font-size: 14px !important;} .layui-font-14{font-size: 14px !important;}
@ -658,6 +681,7 @@ a cite{font-style: normal; *cursor:pointer;}
.layui-font-30{font-size: 30px !important;} .layui-font-30{font-size: 30px !important;}
.layui-font-32{font-size: 32px !important;} .layui-font-32{font-size: 32px !important;}
/* 字体颜色 */
.layui-font-red{color: #ff5722 !important;} /*赤*/ .layui-font-red{color: #ff5722 !important;} /*赤*/
.layui-font-orange{color: #ffb800!important;} /*橙*/ .layui-font-orange{color: #ffb800!important;} /*橙*/
.layui-font-green{color: #16baaa!important;} /*绿*/ .layui-font-green{color: #16baaa!important;} /*绿*/
@ -670,10 +694,8 @@ a cite{font-style: normal; *cursor:pointer;}
/* /*
*
*/
*/
.layui-btn{display: inline-block; vertical-align: middle; height: 38px; line-height: 38px; border: 1px solid transparent; padding: 0 18px; background-color: #16baaa; color: #fff; white-space: nowrap; text-align: center; font-size: 14px; border-radius: 2px; cursor: pointer; -moz-user-select: none; -webkit-user-select: none; -ms-user-select: none;} .layui-btn{display: inline-block; vertical-align: middle; height: 38px; line-height: 38px; border: 1px solid transparent; padding: 0 18px; background-color: #16baaa; color: #fff; white-space: nowrap; text-align: center; font-size: 14px; border-radius: 2px; cursor: pointer; -moz-user-select: none; -webkit-user-select: none; -ms-user-select: none;}
.layui-btn:hover{opacity: 0.8; filter:alpha(opacity=80); color: #fff;} .layui-btn:hover{opacity: 0.8; filter:alpha(opacity=80); color: #fff;}
@ -796,8 +818,8 @@ a cite{font-style: normal; *cursor:pointer;}
.layui-input-wrap .layui-input-number{width: 24px; padding: 0;} .layui-input-wrap .layui-input-number{width: 24px; padding: 0;}
.layui-input-wrap .layui-input-number .layui-icon{position: absolute; right: 0; width: 100%; height: 50%; line-height: normal; font-size: 12px;} .layui-input-wrap .layui-input-number .layui-icon{position: absolute; right: 0; width: 100%; height: 50%; line-height: normal; font-size: 12px;}
.layui-input-wrap .layui-input-number .layui-icon:before{position: absolute; left: 50%; top: 50%; margin-top: -6px; margin-left: -6px;} .layui-input-wrap .layui-input-number .layui-icon:before{position: absolute; left: 50%; top: 50%; margin-top: -6px; margin-left: -6px;}
.layui-input-wrap .layui-input-number .layui-icon:first-child{top: 0; border-bottom: 1px solid #eee;} .layui-input-wrap .layui-input-number .layui-icon-up{top: 0; border-bottom: 1px solid #eee;}
.layui-input-wrap .layui-input-number .layui-icon:last-child{bottom: 0;} .layui-input-wrap .layui-input-number .layui-icon-down{bottom: 0;}
.layui-input-wrap .layui-input-number .layui-icon:hover{font-weight: 700;} .layui-input-wrap .layui-input-number .layui-icon:hover{font-weight: 700;}
.layui-input-wrap .layui-input[type="number"]::-webkit-outer-spin-button, .layui-input-wrap .layui-input[type="number"]::-webkit-outer-spin-button,
.layui-input-wrap .layui-input[type="number"]::-webkit-inner-spin-button{-webkit-appearance: none !important;} .layui-input-wrap .layui-input[type="number"]::-webkit-inner-spin-button{-webkit-appearance: none !important;}
@ -1135,6 +1157,7 @@ select.layui-table-edit{padding: 0 0 0 10px; border-color: #d2d2d2;}
.layui-table-grid-down .layui-icon{position: absolute; top: 50%; left: 50%; margin: -8px 0 0 -8px; font-size: 14px;} .layui-table-grid-down .layui-icon{position: absolute; top: 50%; left: 50%; margin: -8px 0 0 -8px; font-size: 14px;}
.layui-table-grid-down:hover{background-color: #fbfbfb;} .layui-table-grid-down:hover{background-color: #fbfbfb;}
/* 单元格多行展开风格 */
.layui-table-expanded{height: 95px;} .layui-table-expanded{height: 95px;}
.layui-table-expanded .layui-table-cell, .layui-table-expanded .layui-table-cell,
.layui-table-view .layui-table[lay-size="sm"] .layui-table-expanded .layui-table-cell, .layui-table-view .layui-table[lay-size="sm"] .layui-table-expanded .layui-table-cell,
@ -1143,6 +1166,14 @@ select.layui-table-edit{padding: 0 0 0 10px; border-color: #d2d2d2;}
.layui-table-cell-c:hover{border-color: #16b777;} .layui-table-cell-c:hover{border-color: #16b777;}
.layui-table-expanded td:hover .layui-table-cell{overflow: auto;} .layui-table-expanded td:hover .layui-table-cell{overflow: auto;}
/* 单元格 TIPS 展开风格 */
body .layui-table-tips .layui-layer-content{background: none; padding: 0; box-shadow: 0 1px 6px rgba(0,0,0,.12);}
.layui-table-tips-main{margin: -49px 0 0 -1px; max-height: 150px; padding: 8px 15px; font-size: 14px; overflow-y: scroll; background-color: #fff; color: #5F5F5F;}
.layui-table-tips-c{position: absolute; right: -3px; top: -13px; width: 20px; height: 20px; padding: 3px; cursor: pointer; background-color: #5F5F5F; border-radius: 50%; color: #fff;}
.layui-table-tips-c:hover{background-color: #777;}
.layui-table-tips-c:before{position: relative; right: -2px;}
/** 树表 **/ /** 树表 **/
.layui-table-tree-nodeIcon {max-width: 20px;} .layui-table-tree-nodeIcon {max-width: 20px;}
.layui-table-tree-nodeIcon > * {width: 100%;} .layui-table-tree-nodeIcon > * {width: 100%;}
@ -1287,7 +1318,7 @@ select.layui-table-edit{padding: 0 0 0 10px; border-color: #d2d2d2;}
/* 导航浅色背景 */ /* 导航浅色背景 */
.layui-nav.layui-bg-gray .layui-nav-item a, .layui-nav.layui-bg-gray .layui-nav-item a,
.layui-nav-tree.layui-bg-gray a{color: rgba(0,0,0,.8);} .layui-nav-tree.layui-bg-gray a{color: #373737; color: rgba(0,0,0,.8);}
.layui-nav-tree.layui-bg-gray{padding: 6px 0;} .layui-nav-tree.layui-bg-gray{padding: 6px 0;}
.layui-nav-tree.layui-bg-gray .layui-nav-itemed>a{color: #000 !important;} .layui-nav-tree.layui-bg-gray .layui-nav-itemed>a{color: #000 !important;}
.layui-nav.layui-bg-gray .layui-this a{color: #16b777;} .layui-nav.layui-bg-gray .layui-this a{color: #16b777;}
@ -1448,7 +1479,7 @@ body .layui-util-face .layui-layer-content{padding:0; background-color:#fff; co
.layui-util-face ul li:hover{position: relative; z-index: 2; border: 1px solid #eb7350; background: #fff9ec;} .layui-util-face ul li:hover{position: relative; z-index: 2; border: 1px solid #eb7350; background: #fff9ec;}
/** 代码文本修饰 **/ /** 代码文本修饰 **/
.layui-code{position: relative; margin: 10px 0; padding: 15px; line-height: 20px; border: 1px solid #eee; border-left-width: 6px; background-color: #fafafa; color: #333; font-family: Courier New,Lucida Console,Consolas; font-size: 12px;} .layui-code{display: block; position: relative; padding: 15px; line-height: 20px; border: 1px solid #eee; border-left-width: 6px; background-color: #fff; color: #333; font-family: "Courier New",Consolas,"Lucida Console"; font-size: 12px;}
/** 穿梭框 **/ /** 穿梭框 **/
.layui-transfer-box, .layui-transfer-box,

View File

@ -2,59 +2,71 @@
* code * code
*/ */
/* 加载就绪标志 */ html #layuicss-skincodecss{display: none; position: absolute; width: 1989px;}
html #layuicss-skincodecss{display:none; position: absolute; width:1989px;}
/* 默认风格 */ /* 字体 */
.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-wrap{font-size: 13px; font-family: "Courier New",Consolas,"Lucida Console";}
.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{display: block; position: relative; padding: 0 !important; border: 1px solid #eee; border-left-width: 6px; background-color: #fff; color: #333;}
.layui-code-view > .layui-code-ol, .layui-code-view pre{margin: 0 !important;}
.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-header{position: relative; z-index: 3; padding: 0 11px; height: 40px; line-height: 40px; border-bottom: 1px solid #eee; background-color: #fafafa; font-size: 12px;}
.layui-code-view > .layui-code-ol > li:first-child, .layui-code-header > .layui-code-header-about{position: absolute; right: 11px; top: 0; color: #B7B7B7;}
.layui-code-view > .layui-code-ul > li:first-child{padding-top: 10px !important;} .layui-code-header-about > a{padding-left: 10px;}
.layui-code-view > .layui-code-ol > li:last-child,
.layui-code-view > .layui-code-ul > li:last-child{padding-bottom: 10px !important;} .layui-code-wrap{position: relative; display: block; z-index: 1; margin: 0 !important; padding: 11px 0 !important; overflow-x: hidden; overflow-y: auto;}
.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-line{position: relative; line-height: 19px; margin: 0 !important;}
.layui-code-view pre{margin: 0;} .layui-code-line-number{position: absolute; left: 0; top: 0; padding: 0 8px; min-width: 45px; height: 100%; text-align: right; user-select: none; white-space: nowrap; overflow: hidden;}
.layui-code-line-content{padding: 0 11px; word-wrap: break-word; white-space: pre-wrap;}
.layui-code-ln-mode > .layui-code-wrap > .layui-code-line{padding-left: 45px;}
.layui-code-ln-side{position: absolute; left: 0; top: 0; bottom: 0; z-index: 0; width: 45px; border-right: 1px solid #eee; border-color: rgb(126 122 122 / 15%); background-color: #fafafa; pointer-events: none;}
/* 不自动换行 */
.layui-code-nowrap > .layui-code-wrap{overflow: auto;}
.layui-code-nowrap > .layui-code-wrap > .layui-code-line > .layui-code-line-content{white-space: pre; word-wrap: normal;}
.layui-code-nowrap > .layui-code-ln-side{border-right-width: 0 !important; background: none !important;}
.layui-code-fixbar{position: absolute; top: 8px; right: 11px; padding-right: 45px; z-index: 5;}
.layui-code-fixbar > span{position: absolute; right: 0; top: 0; padding: 0 8px; color: #777; transition: all .3s;}
.layui-code-fixbar > span:hover{color: #16b777;}
.layui-code-copy{display: none; cursor: pointer;}
.layui-code-preview > .layui-code-view > .layui-code-fixbar .layui-code-copy{display: none !important;}
.layui-code-view:hover > .layui-code-fixbar .layui-code-copy{display: block;}
.layui-code-view:hover > .layui-code-fixbar .layui-code-lang-marker{display: none;}
/* 深色主题 */
.layui-code-theme-dark{border-width: 1px; border-color: rgb(126 122 122 / 15%); background-color: #1f1f1f; color: #ccc;}
.layui-code-theme-dark > .layui-code-ln-side{border-right-color: #2a2a2a; background: none; color: #6e7681;}
/* 深色风格 */
.layui-code-dark{border: 1px solid #0C0C0C; border-left-color: #3F3F3F; background-color: #0C0C0C; color: #C2BE9E}
.layui-code-dark > .layui-code-title{border-bottom: none;}
.layui-code-dark > .layui-code-ol > li,
.layui-code-dark > .layui-code-ul > li{background-color: #3F3F3F; border-left: none;}
.layui-code-dark > .layui-code-ul > li{margin-left: 6px;}
/* 代码预览 */ /* 代码预览 */
.layui-code textarea{display: none;} .layui-code textarea{display: none;}
.layui-code-preview > .layui-code{margin: 0;} .layui-code-preview > .layui-code,
.layui-code-preview > .layui-code-view{margin: 0;}
.layui-code-preview > .layui-tab{position: relative; z-index: 1; margin-bottom: 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-tab > .layui-tab-title{border-width: 0;}
.layui-code-preview > .layui-code > .layui-code-title{display: none;}
.layui-code-preview .layui-code-item{display: none;} .layui-code-preview .layui-code-item{display: none;}
.layui-code-preview .layui-code-view > .layui-code-ol > li{} .layui-code-preview .layui-code-view > .layui-code-lines > .layui-code-line{}
.layui-code-item-preview{position: relative; padding: 16px; overflow: auto;} .layui-code-item-preview{position: relative; padding: 16px; overflow: auto;}
.layui-code-item-preview > iframe{position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: none;} .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{position: absolute; right: 11px; top: 8px; line-height: normal;}
.layui-code-tools > i{display: inline-block; margin-left: 6px; padding: 3px; cursor: pointer;} .layui-code-tools > i{display: inline-block; margin-left: 6px; padding: 3px; cursor: pointer;}
.layui-code-tools > i.layui-icon-file-b{color: #999;} .layui-code-tools > i.layui-icon-file-b{color: #999;}
.layui-code-tools > i:hover{color: #16b777;} .layui-code-tools > i:hover{color: #16b777;}
/* 复制 */
.layui-code-copy{position: absolute; right: 6px; top: 6px; cursor: pointer; display: none;}
.layui-code-copy .layui-icon{color: #777; transition: all .3s;}
.layui-code-copy:hover .layui-icon{color: #16b777;}
.layui-code-view:hover > .layui-code-copy{display: block;}
.layui-code-copy-offset{margin-right: 17px;}
.layui-code-preview > .layui-code-view > .layui-code-copy{display: none !important;}
/* 全屏风格 */ /* 全屏风格 */
.layui-code-full{position: fixed; left: 0; top: 0; z-index: 1111111; width: 100%; height: 100%; background-color: #fff;} .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{width: 100% !important; border-width: 0 !important; border-top-width: 1px !important;}
.layui-code-full .layui-code-item, .layui-code-full .layui-code-item,
.layui-code-full .layui-code-ol, .layui-code-full .layui-code-view,
.layui-code-full .layui-code-ul{height: calc(100vh - 51px) !important; box-sizing: border-box;} .layui-code-full .layui-code-wrap{height: calc(100vh - 51px) !important; box-sizing: border-box;}
/* 代码高亮重置 */
.layui-code-view.layui-code-hl{line-height: 20px !important; border-left-width: 1px;}
.layui-code-view.layui-code-hl > .layui-code-ln-side{background-color: transparent;}
.layui-code-theme-dark.layui-code-hl,
.layui-code-theme-dark.layui-code-hl > .layui-code-ln-side{border-color: rgb(126 122 122 / 15%);}

View File

@ -16,7 +16,7 @@
}; };
var Layui = function(){ var Layui = function(){
this.v = '2.8.16'; // Layui 版本号 this.v = '2.8.17'; // Layui 版本号
}; };
// 识别预先可能定义的指定全局对象 // 识别预先可能定义的指定全局对象

View File

@ -1,32 +1,38 @@
/** /**
* code * code
* Code 预览组件 * Code 预览组件
*/ */
layui.define(['lay', 'util', 'element', 'form'], function(exports){ layui.define(['lay', 'util', 'element', 'form'], function(exports){
"use strict"; "use strict";
var $ = layui.$; var $ = layui.$;
var util = layui.util; var util = layui.util;
var element = layui.element; var element = layui.element;
var form = layui.form; var form = layui.form;
var layer = layui.layer; var layer = layui.layer;
var hint = layui.hint();
// 常量 // 常量
var CONST = { var CONST = {
ELEM_VIEW: 'layui-code-view', ELEM_VIEW: 'layui-code-view',
ELEM_COPY: 'layui-code-copy',
ELEM_TAB: 'layui-tab', ELEM_TAB: 'layui-tab',
ELEM_TITLE: 'layui-code-title', ELEM_HEADER: 'layui-code-header',
ELEM_FULL: 'layui-code-full', ELEM_FULL: 'layui-code-full',
ELEM_PREVIEW: 'layui-code-preview', ELEM_PREVIEW: 'layui-code-preview',
ELEM_ITEM: 'layui-code-item', ELEM_ITEM: 'layui-code-item',
ELEM_SHOW: 'layui-show' ELEM_SHOW: 'layui-show',
ELEM_LINE: 'layui-code-line',
ELEM_LINE_NUM: 'layui-code-line-number',
ELEM_LN_MODE: 'layui-code-ln-mode',
CDDE_DATA_CODE: 'LayuiCodeDataCode',
CDDE_DATA_CLASS: 'LayuiCodeDataClass',
LINE_RAW_WIDTH: 45, // 行号初始宽度,需与 css 保持一致
}; };
// 默认参数项 // 默认参数项
var config = { var config = {
elem: '.layui-code', // 元素选择器 elem: '', // 元素选择器
about: '', // 代码栏右上角信息 about: '', // 代码栏右上角信息
ln: true, // 代码区域是否显示行号 ln: true, // 代码区域是否显示行号
header: false, // 是否显示代码栏头部区域 header: false, // 是否显示代码栏头部区域
@ -35,345 +41,562 @@ layui.define(['lay', 'util', 'element', 'form'], function(exports){
// 默认文本 // 默认文本
text: { text: {
code: util.escape('</>'), code: util.escape('</>'),
preview: 'Preview' preview: 'Preview',
} },
wordWrap: true, // 是否自动换行
lang: 'text', // 指定语言类型
highlighter: false, // 是否开启语法高亮,'hljs','prism','shiki'
langMarker: false, // 代码区域是否显示语言类型标记
}; };
// 初始索引
var codeIndex = layui.code ? (layui.code.index + 10000) : 0;
// 去除尾部空格
var trimEnd = function(str){
return String(str).replace(/\s+$/, '');
}
// 保留首行缩进
var trim = function(str){ var trim = function(str){
return $.trim(str).replace(/^\n|\n$/, ''); return trimEnd(str).replace(/^\n|\n$/, '');
}; };
// export api // export api
exports('code', function(options){ exports('code', function(options, mode){
var opts = options = $.extend(true, {}, config, options); options = $.extend(true, {}, config, options);
// 返回对象
var ret = {
config: options,
reload: function(opts) { // 重载
layui.code(this.updateOptions(opts));
},
updateOptions: function(opts) { // 更新属性(选项)
opts = opts || {};
delete opts.elem;
return $.extend(true, options, opts);
},
reloadCode: function(opts) { // 仅重载 code
layui.code(this.updateOptions(opts), 'reloadCode');
}
};
// 若 elem 非唯一
var elem = $(options.elem);
if(elem.length > 1){
// 是否正向渲染
layui.each(options.obverse ? elem : elem.get().reverse(), function(){
layui.code($.extend({}, options, {
elem: this
}), mode);
});
return ret;
}
// 目标元素是否存在 // 目标元素是否存在
options.elem = $(options.elem); var othis = options.elem = $(options.elem);
if(!options.elem[0]) return; if(!othis[0]) return ret;
// 从内至外渲染 // 合并属性上的参数,并兼容旧版本属性写法 lay-*
layui.each(options.elem.get().reverse(), function(index, item){ $.extend(true, options, lay.options(othis[0]), function(obj){
var othis = $(item); var attrs = ['title', 'height', 'encode', 'skin', 'about'];
layui.each(attrs, function(i, attr){
// 合并属性上的参数,并兼容旧版本属性写法 lay-* var value = othis.attr('lay-'+ attr);
var options = $.extend(true, {}, opts, lay.options(item), function(obj){ if(typeof value === 'string'){
var attrs = ['title', 'height', 'encode', 'skin', 'about']; obj[attr] = value;
layui.each(attrs, function(i, attr){
var value = othis.attr('lay-'+ attr);
if(typeof value === 'string'){
obj[attr] = value;
}
})
return obj;
}({}));
// 最终显示的代码
var finalCode;
// 获得初始代码
var codes = othis.data('code') || function(){
var arr = [];
var textarea = othis.children('textarea');
// 若内容放置在 textarea 中
textarea.each(function(){
arr.push(trim(this.value));
});
// 内容直接放置在元素外层
if(arr.length === 0){
arr.push(trim(othis.html()));
} }
})
return arr; return obj;
}(); }({}));
othis.data('code', codes); // codeRender 需要关闭编码
// 未使用 codeRender 时若开启了预览,则强制开启编码
options.encode = (options.encode || options.preview) && !options.codeRender;
// code // 最终显示的代码
var html = finalCode = codes.join(''); var finalCode;
// 外部重新解析 code // 获得初始 code
if(typeof options.codeParse === 'function'){ var rawCode = othis.data(CONST.CDDE_DATA_CODE) || function(){
html = finalCode = options.codeParse(html); var arr = [];
var textarea = othis.children('textarea');
// 若内容放置在 textarea 中
textarea.each(function(){
arr.push(trim(this.value));
});
// 内容直接放置在元素外层
if(arr.length === 0){
arr.push(trim(othis.html()));
} }
return arr;
}();
// 记录初始 code
othis.data(CONST.CDDE_DATA_CODE, rawCode);
// 创建 code 行结构
var createCode = function(html) {
// codeRender
if(typeof options.codeRender === 'function') {
html = options.codeRender(String(html), options);
}
// code 行
var lines = String(html).split(/\r?\n/g);
// 包裹 code 行结构
html = $.map(lines, function(line, num) {
return [
'<div class="'+ CONST.ELEM_LINE +'">',
(
options.ln ? [
'<div class="'+ CONST.ELEM_LINE_NUM +'">',
(util.digit(num + 1) + '.'),
'</div>',
].join('') : ''
),
'<div class="layui-code-line-content">',
(line || ' '),
'</div>',
'</div>'
].join('');
});
return {
lines: lines,
html: html
};
};
// 仅重载 code
if (mode === 'reloadCode') {
(function(html) {
var rst = createCode(html);
othis.children('.layui-code-wrap').html(rst.html);
})(rawCode.join(''))
return ret;
}
// 自增索引
var index = layui.code.index = ++codeIndex;
othis.attr('lay-code-index', index);
// 初始化 className
var hasDataClass = CONST.CDDE_DATA_CLASS in othis.data();
if (hasDataClass) {
othis.attr('class', othis.data(CONST.CDDE_DATA_CLASS) || '');
}
// 记录初始 className
if (!hasDataClass) {
othis.data(CONST.CDDE_DATA_CLASS, othis.attr('class'));
}
// code
var html = finalCode = rawCode.join('');
// 外部重新解析 code
if(typeof options.codeParse === 'function'){
html = finalCode = options.codeParse(html);
}
// 工具栏
var tools = {
copy: {
className: 'file-b',
title: ['复制代码'],
event: function(obj){
var code = util.unescape(finalCode);
// 写入剪切板
lay.clipboard.writeText({
text: code,
done: function() {
layer.msg('已复制', {icon: 1});
},
error: function() {
layer.msg('复制失败', {icon: 2});
}
});
typeof options.onCopy === 'function' && options.onCopy(code);
}
}
};
// 移除包裹结构
var unwrap = (function fn() {
var elemViewHas = othis.parent('.' + CONST.ELEM_PREVIEW);
var elemTabHas = elemViewHas.children('.'+ CONST.ELEM_TAB);
var elemPreviewViewHas = elemViewHas.children('.' + CONST.ELEM_ITEM +'-preview');
// 移除旧结构
elemTabHas.remove(); // 移除 tab
elemPreviewViewHas.remove(); // 移除预览区域
if (elemViewHas[0]) othis.unwrap(); // 移除外层容器
return fn;
})();
// 是否开启预览
if(options.preview){
var FILTER_VALUE = 'LAY-CODE-DF-'+ index;
var layout = options.layout || ['code', 'preview'];
var isIframePreview = options.preview === 'iframe';
// 追加 Tab 组件
var elemView = $('<div class="'+ CONST.ELEM_PREVIEW +'">');
var elemTabView = $('<div class="layui-tab layui-tab-brief">');
var elemHeaderView = $('<div class="layui-tab-title">');
var elemPreviewView = $('<div class="'+ [
CONST.ELEM_ITEM,
CONST.ELEM_ITEM +'-preview',
'layui-border'
].join(' ') +'">');
var elemToolbar = $('<div class="layui-code-tools"></div>');
if(options.id) elemView.attr('id', options.id);
elemView.addClass(options.className);
elemTabView.attr('lay-filter', FILTER_VALUE);
// 标签头
layui.each(layout, function(i, v){
var li = $('<li lay-id="'+ v +'">');
if(i === 0) li.addClass('layui-this');
li.html(options.text[v]);
elemHeaderView.append(li);
});
// 工具栏 // 工具栏
var tools = { $.extend(tools, {
copy: { 'full': {
className: 'file-b', className: 'screen-full',
title: ['复制代码'], title: ['最大化显示', '还原显示'],
event: function(el, type){ event: function(obj){
var text = util.unescape(finalCode); var el = obj.elem;
try { var elemView = el.closest('.'+ CONST.ELEM_PREVIEW);
navigator.clipboard.writeText(text).then(function(){ var classNameFull = 'layui-icon-'+ this.className;
layer.msg('已复制', {icon: 1}); var classNameRestore = 'layui-icon-screen-restore';
}); var title = this.title;
} catch(e) { var html = $('html,body');
var textarea = document.createElement('textarea'); var ELEM_SCROLLBAR_HIDE = 'layui-scrollbar-hide';
textarea.value = text;
textarea.style.position = 'absolute'; if(el.hasClass(classNameFull)){
textarea.style.opacity = '0'; elemView.addClass(CONST.ELEM_FULL);
document.body.appendChild(textarea); el.removeClass(classNameFull).addClass(classNameRestore);
textarea.select(); el.attr('title', title[1]);
try { html.addClass(ELEM_SCROLLBAR_HIDE);
document.execCommand('copy'); } else {
layer.msg('已复制', {icon: 1}); elemView.removeClass(CONST.ELEM_FULL);
} catch(err) { el.removeClass(classNameRestore).addClass(classNameFull);
layer.msg('复制失败', {icon: 2}); el.attr('title', title[0]);
} html.removeClass(ELEM_SCROLLBAR_HIDE);
textarea.remove();
} }
typeof options.onCopy === 'function' && options.onCopy(text); }
},
'window': {
className: 'release',
title: ['在新窗口预览'],
event: function(obj){
util.openWin({
content: finalCode
});
} }
} }
}; });
// 是否开启预览 // copy
if(options.preview){ if(options.copy){
var FILTER_VALUE = 'LAY-CODE-DF-'+ index; if(layui.type(options.tools) === 'array'){
var layout = options.layout || ['code', 'preview']; // 若 copy 未存在于 tools 中,则追加到最前
var isIframePreview = options.preview === 'iframe'; if(options.tools.indexOf('copy') === -1){
options.tools.unshift('copy');
// 追加 Tab 组件
var elemView = $('<div class="'+ CONST.ELEM_PREVIEW +'">');
var elemTabView = $('<div class="layui-tab layui-tab-brief">');
var elemHeaderView = $('<div class="layui-tab-title">');
var elemPreviewView = $('<div class="'+ [
CONST.ELEM_ITEM,
CONST.ELEM_ITEM +'-preview',
'layui-border'
].join(' ') +'">');
var elemToolbar = $('<div class="layui-code-tools"></div>');
var elemViewHas = othis.parent('.' + CONST.ELEM_PREVIEW);
var elemTabHas = othis.prev('.'+ CONST.ELEM_TAB);
var elemPreviewViewHas = othis.next('.' + CONST.ELEM_ITEM +'-preview');
if(options.id) elemView.attr('id', options.id);
elemView.addClass(options.className);
elemTabView.attr('lay-filter', FILTER_VALUE);
// 若开启预览,则强制对 code 进行编码
options.encode = true;
// 标签头
layui.each(layout, function(i, v){
var li = $('<li lay-id="'+ v +'">');
if(i === 0) li.addClass('layui-this');
li.html(options.text[v]);
elemHeaderView.append(li);
});
// 工具栏
$.extend(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_SCROLLBAR_HIDE = 'layui-scrollbar-hide';
if(el.hasClass(classNameFull)){
elemView.addClass(CONST.ELEM_FULL);
el.removeClass(classNameFull).addClass(classNameRestore);
el.attr('title', title[1]);
html.addClass(ELEM_SCROLLBAR_HIDE);
} else {
elemView.removeClass(CONST.ELEM_FULL);
el.removeClass(classNameRestore).addClass(classNameFull);
el.attr('title', title[0]);
html.removeClass(ELEM_SCROLLBAR_HIDE);
}
}
},
'window': {
className: 'release',
title: ['在新窗口预览'],
event: function(el, type){
util.openWin({
content: finalCode
});
}
}
});
// copy
if(options.copy){
if(layui.type(options.tools) === 'array'){
// 若 copy 未存在于 tools 中,则追加到最前
if(options.tools.indexOf('copy') === -1){
options.tools.unshift('copy');
}
} else {
options.tools = ['copy'];
} }
} else {
options.tools = ['copy'];
} }
}
// 工具栏事件 // 工具栏事件
elemToolbar.on('click', '>i', function(){ elemToolbar.on('click', '>i', function(){
var oi = $(this); var oi = $(this);
var type = oi.data('type'); var type = oi.data('type');
tools[type] && typeof tools[type].event === 'function' && tools[type].event(oi, type); var parameters = {
typeof options.toolsEvent === 'function' && options.toolsEvent(oi, type); elem: oi,
}); type: type,
layui.each(options.tools, function(i, v){ options: options, // 当前属性选项
var className = (tools[v] && tools[v].className) || v; rawCode: rawCode.join(''), // 原始 code
var title = (tools[v] && tools[v].title) || ['']; finalCode: util.unescape(finalCode) // 最终 code
elemToolbar.append(
'<i class="layui-icon layui-icon-'+ className +'" data-type="'+ v +'" title="'+ title[0] +'"></i>'
);
});
// 移除旧结构
if(elemTabHas[0]) elemTabHas.remove(); // 移除 tab
if(elemPreviewViewHas[0]) elemPreviewViewHas.remove(); // 移除预览区域
if(elemViewHas[0]) othis.unwrap(); // 移除外层容器
elemTabView.append(elemHeaderView); // 追加标签头
options.tools && elemTabView.append(elemToolbar); // 追加工具栏
othis.wrap(elemView).addClass(CONST.ELEM_ITEM).before(elemTabView); // 追加标签结构
// 追加预览
if(isIframePreview){
elemPreviewView.html('<iframe allowtransparency="true" frameborder="0"></iframe>');
}
// 执行预览
var run = function(thisItemBody){
var iframe = thisItemBody.children('iframe')[0];
if(isIframePreview && iframe){
iframe.srcdoc = finalCode;
} 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'){ // 内部 tools event
elemPreviewView.addClass(CONST.ELEM_SHOW); tools[type] && typeof tools[type].event === 'function' && tools[type].event(parameters);
othis.before(elemPreviewView);
run(elemPreviewView);
} else {
othis.addClass(CONST.ELEM_SHOW).after(elemPreviewView);
}
// 内容项初始化样式 // 外部 tools event
options.codeStyle = [options.style, options.codeStyle].join(''); typeof options.toolsEvent === 'function' && options.toolsEvent(parameters);
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){ if (options.addTools) {
var $this = $(this); options.tools = [].concat(options.tools || [], options.addTools);
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); layui.each(options.tools, function(i, v){
var viso = typeof v === 'object'; // 若为 object 值,则可自定义更多属性
var tool = viso ? v : (
tools[v] || {
className: v,
title: [v]
} }
}); );
}
// 有序或无序列表 var className = tool.className || tool.type;
var listTag = options.ln ? 'ol' : 'ul'; var title = tool.title || [''];
var listElem = $('<'+ listTag +' class="layui-code-'+ listTag +'">'); var type = viso ? ( tool.type || className ) : v;
// header if (!type) return;
var headerElem = $('<div class="'+ CONST.ELEM_TITLE +'">');
// 添加组件 className // 若非内置 tool则合并到 tools 中
othis.addClass('layui-code-view layui-box'); if (!tools[type]) {
var obj = {};
// 自定义风格 obj[type] = tool;
if(options.skin){ $.extend(tools, obj);
if(options.skin === 'notepad') options.skin = 'dark';
othis.removeClass('layui-code-dark layui-code-light');
othis.addClass('layui-code-'+ options.skin);
}
// 转义 HTML 标签
if(options.encode) html = util.escape(html); // 编码
html = html.replace(/[\r\t\n]+/g, '</li><li>'); // 转义换行符
// 生成列表
othis.html(listElem.html('<li>' + html + '</li>'));
// 创建 header
if(options.header && !othis.children('.'+ CONST.ELEM_TITLE)[0]){
headerElem.html((options.title || options.text.code) + (
options.about
? '<div class="layui-code-about">' + options.about + '</div>'
: ''
));
othis.prepend(headerElem);
}
// 所有实例渲染完毕后的回调
if(options.elem.length === index + 1){
typeof options.allDone === 'function' && options.allDone();
}
// 按行数适配左边距
(function(autoIncNums){
if(autoIncNums > 0){
listElem.css('margin-left', autoIncNums + 'px');
} }
})(Math.floor(listElem.find('li').length/100));
// 限制 Code 最大高度 elemToolbar.append(
if(options.height){ // 兼容旧版本 '<i class="layui-icon layui-icon-'+ className +'" data-type="'+ type +'" title="'+ title[0] +'"></i>'
listElem.css('max-height', options.height); );
} });
// Code 内容区域样式
listElem.attr('style', options.codeStyle);
// 是否开启代码复制 othis.addClass(CONST.ELEM_ITEM).wrap(elemView); // 包裹外层容器
if(options.copy && !options.preview){ elemTabView.append(elemHeaderView); // 追加标签头
var elemCopy = $(['<span class="'+ CONST.ELEM_COPY +'">', options.tools && elemTabView.append(elemToolbar); // 追加工具栏
'<i class="layui-icon layui-icon-file-b" title="复制"></i>', othis.before(elemTabView); // 追加标签结构
'</span>'].join(''));
var elemCopyHas = othis.children('.'+ CONST.ELEM_COPY);
var isHeight = listElem[0].style.height || listElem[0].style.maxHeight;
if(isHeight) elemCopy.addClass(CONST.ELEM_COPY + '-offset'); // 偏移 // 追加预览
if(elemCopyHas[0]) elemCopyHas.remove(); // 移除旧的复制元素 if(isIframePreview){
othis.append(elemCopy); elemPreviewView.html('<iframe allowtransparency="true" frameborder="0"></iframe>');
// 点击复制
elemCopy.on('click', function(){
tools.copy.event();
});
} }
}); // 执行预览
var run = function(thisItemBody){
var iframe = thisItemBody.children('iframe')[0];
if(isIframePreview && iframe){
iframe.srcdoc = finalCode;
} else {
thisItemBody.html(rawCode.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.previewStyle = [options.style, options.previewStyle].join('');
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);
}
setCodeLayout();
});
}
// 创建 code 容器
var codeElem = $('<code class="layui-code-wrap"></code>'); // 此处的闭合标签是为了兼容 IE8
// 添加主容器 className
othis.addClass(function(arr) {
if (!options.wordWrap) arr.push('layui-code-nowrap');
return arr.join(' ')
}(['layui-code-view layui-border-box']));
// code 主题风格
var theme = options.theme || options.skin;
if (theme) {
othis.removeClass('layui-code-theme-dark layui-code-theme-light');
othis.addClass('layui-code-theme-'+ theme);
}
// 添加高亮必要的 className
if (options.highlighter) {
othis.addClass([
options.highlighter,
'language-' + options.lang,
'layui-code-hl'
].join(' '));
}
// 转义 HTML 标签
if(options.encode) html = util.escape(html); // 编码
var createCodeRst = createCode(html);
var lines = createCodeRst.lines;
// 插入 code
othis.html(codeElem.html(createCodeRst.html));
// 插入行号边栏
if (options.ln) {
othis.append('<div class="layui-code-ln-side"></div>');
}
// 兼容旧版本 height 属性
if (options.height) {
codeElem.css('max-height', options.height);
}
// code 区域样式
options.codeStyle = [options.style, options.codeStyle].join('');
if (options.codeStyle) {
codeElem.attr('style', function(i, val) {
return (val || '') + options.codeStyle;
});
}
// 动态设置样式
var cssRules = [
{
selector: '>.layui-code-wrap>.layui-code-line{}',
setValue: function(item, value) {
item.style['padding-left'] = value + 'px';
}
},
{
selector: '>.layui-code-wrap>.layui-code-line>.layui-code-line-number{}',
setValue: function(item, value) {
item.style.width = value + 'px';
}
},
{
selector: '>.layui-code-ln-side{}',
setValue: function(item, value) {
item.style.width = value + 'px';
}
}
];
// 生成初始 style 元素
var styleElem = lay.style({
target: othis[0],
id: 'DF-code-'+ index,
text: $.map($.map(cssRules, function(val){
return val.selector;
}), function(val, i) {
return ['.layui-code-view[lay-code-index="'+ index + '"]', val].join(' ');
}).join('')
})
// 动态设置 code 布局
var setCodeLayout = (function fn() {
if (options.ln) {
var multiLine = Math.floor(lines.length / 100);
var lineElem = codeElem.children('.'+ CONST.ELEM_LINE);
var width = lineElem.last().children('.'+ CONST.ELEM_LINE_NUM).outerWidth();
othis.addClass(CONST.ELEM_LN_MODE);
// 若超出 100 行
if (multiLine && width > CONST.LINE_RAW_WIDTH) {
lay.getStyleRules(styleElem, function(item, i) {
try {
cssRules[i].setValue(item, width);
} catch(e) { }
});
}
}
return fn;
})();
// 创建 code header
if (options.header) {
var headerElem = $('<div class="'+ CONST.ELEM_HEADER +'"></div>');
headerElem.html(options.title || options.text.code);
othis.prepend(headerElem);
}
// 创建 code 区域固定条
var elemFixbar = $('<div class="layui-code-fixbar"></div>');
// 若开启复制,且未开启预览,则单独生成复制图标
if(options.copy && !options.preview){
var copyElem = $(['<span class="layui-code-copy">',
'<i class="layui-icon layui-icon-file-b" title="复制"></i>',
'</span>'].join(''));
// 点击复制
copyElem.on('click', function(){
tools.copy.event();
});
elemFixbar.append(copyElem);
}
// 创建 language marker
if (options.langMarker) {
elemFixbar.append('<span class="layui-code-lang-marker">' + options.lang + '</span>');
}
// 创建 about 自定义内容
if (options.about) {
elemFixbar.append(options.about);
}
// 生成 code fixbar
othis.append(elemFixbar);
// code 渲染完毕后的回调
if (!options.preview) {
setTimeout(function(){
typeof options.done === 'function' && options.done({});
},3);
}
// 所有实例渲染完毕后的回调
if(options.elem.length === index + 1){
typeof options.allDone === 'function' && options.allDone();
}
return ret;
}); });
}); });
// 若为源码版,则自动加载该组件依赖的 css 文件 // 若为源码版,则自动加载该组件依赖的 css 文件
if(!layui['layui.all']){ if(!layui['layui.all']){
layui.addcss('modules/code.css?v=3', 'skincodecss'); layui.addcss('modules/code.css?v=6', 'skincodecss');
} }

View File

@ -11,42 +11,58 @@ layui.define(['lay', 'layer', 'util'], function(exports){
var hint = layui.hint(); var hint = layui.hint();
var device = layui.device(); var device = layui.device();
var MOD_NAME = 'form', ELEM = '.layui-form', THIS = 'layui-this'; var MOD_NAME = 'form';
var SHOW = 'layui-show', HIDE = 'layui-hide', DISABLED = 'layui-disabled'; var ELEM = '.layui-form';
var THIS = 'layui-this';
var SHOW = 'layui-show';
var HIDE = 'layui-hide';
var DISABLED = 'layui-disabled';
var Form = function(){ var Form = function(){
this.config = { this.config = {
// 内置的验证规则 // 内置的验证规则
verify: { verify: {
required: [ required: function(value) {
/[\S]+/, if (!/[\S]+/.test(value)) {
'必填项不能为空' return '必填项不能为空';
], }
phone: [
/^1\d{10}$/,
'请输入正确的手机号'
],
email: [
/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/,
'邮箱格式不正确'
],
url: [
/^(#|(http(s?)):\/\/|\/\/)[^\s]+\.[^\s]+$/,
'链接格式不正确'
],
number: function(value){
if(isNaN(value)) return '只能填写数字';
}, },
date: [ phone: function(value) {
/^(\d{4})[-\/](\d{1}|0\d{1}|1[0-2])([-\/](\d{1}|0\d{1}|[1-2][0-9]|3[0-1]))*$/, var EXP = /^1\d{10}$/;
'日期格式不正确' if (value && !EXP.test(value)) {
], return '手机号格式不正确';
identity: [ }
/(^\d{15}$)|(^\d{17}(x|X|\d)$)/, },
'请输入正确的身份证号' email: function(value) {
] var EXP = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
if (value && !EXP.test(value)) {
return '邮箱格式不正确';
}
},
url: function(value) {
var EXP = /^(#|(http(s?)):\/\/|\/\/)[^\s]+\.[^\s]+$/;
if (value && !EXP.test(value)) {
return '链接格式不正确';
}
},
number: function(value){
if (value && isNaN(value)) {
return '只能填写数字';
}
},
date: function(value){
var EXP = /^(\d{4})[-\/](\d{1}|0\d{1}|1[0-2])([-\/](\d{1}|0\d{1}|[1-2][0-9]|3[0-1]))*$/;
if (value && !EXP.test(value)) {
return '日期格式不正确';
}
},
identity: function(value) {
var EXP = /(^\d{15}$)|(^\d{17}(x|X|\d)$)/;
if (value && !EXP.test(value)) {
return '身份证号格式不正确';
}
}
}, },
verIncludeRequired: false, // 验证规则是否包含必填 --- 为兼容旧版的验证机制
autocomplete: null // 全局 autocomplete 状态。 null 表示不干预 autocomplete: null // 全局 autocomplete 状态。 null 表示不干预
}; };
}; };
@ -894,10 +910,10 @@ layui.define(['lay', 'layer', 'util'], function(exports){
return that; return that;
}; };
// 主动触发验证 -- elem 即要验证的区域表单选择器 / return true or false // 主动触发验证 --- elem 即要验证的区域表单选择器 / return true or false
Form.prototype.validate = function(elem){ Form.prototype.validate = function(elem) {
var that = this; var that = this;
var stop = null; // 验证不通过状态 var intercept; // 拦截标识
var options = that.config; // 获取全局配置项 var options = that.config; // 获取全局配置项
var verify = options.verify; // 验证规则 var verify = options.verify; // 验证规则
var DANGER = 'layui-form-danger'; // 警示样式 var DANGER = 'layui-form-danger'; // 警示样式
@ -905,10 +921,10 @@ layui.define(['lay', 'layer', 'util'], function(exports){
elem = $(elem); elem = $(elem);
// 节点不存在可视为 true // 节点不存在可视为 true
if(!elem[0]) return !0; if (!elem[0]) return !0;
// 若节点不存在特定属性,则查找容器内有待验证的子节点 // 若节点不存在特定属性,则查找容器内有待验证的子节点
if(elem.attr('lay-verify') === undefined){ if (elem.attr('lay-verify') === undefined) {
// 若校验的是一个不带验证规则的容器,校验内部的 lay-verify 节点 // 若校验的是一个不带验证规则的容器,校验内部的 lay-verify 节点
if (that.validate(elem.find('*[lay-verify]')) === false) { if (that.validate(elem.find('*[lay-verify]')) === false) {
return false; return false;
@ -916,7 +932,7 @@ layui.define(['lay', 'layer', 'util'], function(exports){
} }
// 开始校验 // 开始校验
layui.each(elem, function(_, item){ layui.each(elem, function(_, item) {
var othis = $(this); var othis = $(this);
var verifyStr = othis.attr('lay-verify') || ''; var verifyStr = othis.attr('lay-verify') || '';
var vers = verifyStr.split('|'); var vers = verifyStr.split('|');
@ -926,16 +942,16 @@ layui.define(['lay', 'layer', 'util'], function(exports){
othis.removeClass(DANGER); // 移除警示样式 othis.removeClass(DANGER); // 移除警示样式
// 遍历元素绑定的验证规则 // 遍历元素绑定的验证规则
layui.each(vers, function(_, thisVer){ layui.each(vers, function(_, thisVer) {
var isTrue; // 是否命中校验 var verst; // 校验结果
var errorText = ''; // 错误提示文本 var errorText = ''; // 错误提示文本
var rule = verify[thisVer]; // 获取校验规则 var rule = verify[thisVer]; // 获取校验规则
// 匹配验证规则 // 匹配验证规则
if(rule){ if (rule) {
isTrue = typeof rule === 'function' verst = typeof rule === 'function'
? errorText = rule(value, item) ? errorText = rule(value, item)
: !rule[0].test(value); : !rule[0].test(value); // 兼容早期数组中的正则写法
// 是否属于美化替换后的表单元素 // 是否属于美化替换后的表单元素
var isForm2Elem = item.tagName.toLowerCase() === 'select' || ( var isForm2Elem = item.tagName.toLowerCase() === 'select' || (
@ -945,20 +961,14 @@ layui.define(['lay', 'layer', 'util'], function(exports){
errorText = errorText || rule[1]; errorText = errorText || rule[1];
// 获取自定义必填项提示文本 // 获取自定义必填项提示文本
if(thisVer === 'required'){ if (thisVer === 'required') {
errorText = othis.attr('lay-reqtext') || errorText; errorText = othis.attr('lay-reqtext') || errorText;
} }
// 若为必填项或者非空命中校验,则阻止提交,弹出提示 // 若命中校验规则
if(isTrue && ( if (verst) {
options.verIncludeRequired || (
thisVer === 'required' || (
value && thisVer !== 'required'
)
)
)){
// 提示层风格 // 提示层风格
if(verType === 'tips'){ if (verType === 'tips') {
layer.tips(errorText, function(){ layer.tips(errorText, function(){
if(typeof othis.attr('lay-ignore') !== 'string'){ if(typeof othis.attr('lay-ignore') !== 'string'){
if(isForm2Elem){ if(isForm2Elem){
@ -971,24 +981,24 @@ layui.define(['lay', 'layer', 'util'], function(exports){
layer.alert(errorText, {title: '提示', shadeClose: true}); layer.alert(errorText, {title: '提示', shadeClose: true});
} }
// 若返回的为字符或数字,则自动弹出默认提示框;否则由 verify 方法中处理提示 // 若返回的为字符或数字,则自动弹出默认提示框;否则由 verify 方法中处理提示
else if(/\b(string|number)\b/.test(typeof errorText)){ else if(/\b(string|number)\b/.test(typeof errorText)) {
layer.msg(errorText, {icon: 5, shift: 6}); layer.msg(errorText, {icon: 5, shift: 6});
} }
setTimeout(function(){ setTimeout(function() {
(isForm2Elem ? othis.next().find('input') : item).focus(); (isForm2Elem ? othis.next().find('input') : item).focus();
}, 7); }, 7);
othis.addClass(DANGER); othis.addClass(DANGER);
return stop = true; return intercept = true;
} }
} }
}); });
if(stop) return stop; if (intercept) return intercept;
}); });
return !stop; return !intercept;
}; };
// 提交表单并校验 // 提交表单并校验

View File

@ -27,6 +27,21 @@
that.push(elem[index]); that.push(elem[index]);
}); });
}; };
/*
* API 兼容
*/
Array.prototype.indexOf = Array.prototype.indexOf || function(searchElement, fromIndex) {
var rst = -1;
fromIndex = fromIndex || 0;
layui.each(this, function(index, val){
if (searchElement === val && index >= fromIndex) {
rst = index;
return !0;
}
});
return rst;
};
/* /*
lay 对象操作 lay 对象操作
@ -120,7 +135,7 @@
if (typeof callback === 'function') { if (typeof callback === 'function') {
layui.each(rules, function(i, item){ layui.each(rules, function(i, item){
if (callback(item)) return true; if (callback(item, i)) return true;
}); });
} }
@ -294,6 +309,40 @@
return matched; return matched;
}; };
// 剪切板
lay.clipboard = {
// 写入文本
writeText: function(options) {
var text = String(options.text);
try {
navigator.clipboard.writeText(text).then(
options.done
)['catch'](options.error);
} catch(e) {
var elem = document.createElement('textarea');
elem.value = text;
elem.style.position = 'fixed';
elem.style.opacity = '0';
elem.style.top = '0px';
elem.style.left = '0px';
document.body.appendChild(elem);
elem.select();
try {
document.execCommand('copy');
typeof options.done === 'function' && options.done();
} catch(err) {
typeof options.error === 'function' && options.error(err);
} finally {
elem.remove ? elem.remove() : document.body.removeChild(elem);
}
}
}
};
/* /*
* lay 元素操作 * lay 元素操作

View File

@ -989,11 +989,11 @@
} }
})(); })();
//校验日期有效数字 // 校验日期有效数字
checkValid(dateTime); checkValid(dateTime);
if(options.range) checkValid(that.endDate); if(options.range) checkValid(that.endDate);
//如果初始值格式错误,则纠正初始值 // 如果初始值格式错误,则纠正初始值
if(error && value){ if(error && value){
that.setValue( that.setValue(
options.range ? (that.endDate ? that.parse() : '') : that.parse() options.range ? (that.endDate ? that.parse() : '') : that.parse()
@ -1041,6 +1041,7 @@
that.hint('value ' + lang.invalidDate + lang.formatError[1]); that.hint('value ' + lang.invalidDate + lang.formatError[1]);
} }
// 初始赋值 startDate,endState
that.startDate = that.startDate || value && lay.extend({}, options.dateTime); // 有默认值才初始化startDate that.startDate = that.startDate || value && lay.extend({}, options.dateTime); // 有默认值才初始化startDate
that.autoCalendarModel.auto && that.autoCalendarModel(); that.autoCalendarModel.auto && that.autoCalendarModel();
that.endState = !options.range || !that.rangeLinked || !!(that.startDate && that.endDate); // 初始化选中范围状态 that.endState = !options.range || !that.rangeLinked || !!(that.startDate && that.endDate); // 初始化选中范围状态
@ -1584,21 +1585,22 @@
} }
}; };
//转义为规定格式的日期字符 // 转义为规定格式的日期字符
Class.prototype.parse = function(state, date){ Class.prototype.parse = function(state, date) {
var that = this var that = this;
,options = that.config var options = that.config;
,dateTime = date || (state == 'end' var startDate = (that.rangeLinked ? that.startDate : options.dateTime)
? lay.extend({}, that.endDate, that.endTime) var dateTime = date || (
: ( state == 'end' ? lay.extend({}, that.endDate, that.endTime) : (
options.range options.range
? lay.extend({}, that.rangeLinked ? that.startDate : options.dateTime, that.startTime) ? lay.extend({}, startDate || options.dateTime, that.startTime)
: options.dateTime) : options.dateTime
) )
,format = laydate.parse(dateTime, that.format, 1); );
var format = laydate.parse(dateTime, that.format, 1);
//返回日期范围字符
if(options.range && state === undefined){ // 返回日期范围字符
if (options.range && state === undefined) {
return format + ' '+ that.rangeStr +' ' + that.parse('end'); return format + ' '+ that.rangeStr +' ' + that.parse('end');
} }
@ -1756,12 +1758,14 @@
}); });
}; };
//执行 done/change 回调 // 执行 done/change 回调
Class.prototype.done = function(param, type){ Class.prototype.done = function(param, type){
var that = this var that = this;
,options = that.config var options = that.config;
,start = lay.extend({}, lay.extend(options.dateTime, that.startTime)) var start = lay.extend({},
,end = lay.extend({}, lay.extend(that.endDate, that.endTime)) lay.extend(that.rangeLinked ? that.startDate : options.dateTime, that.startTime)
);
var end = lay.extend({}, lay.extend(that.endDate, that.endTime));
lay.each([start, end], function(i, item){ lay.each([start, end], function(i, item){
if(!('month' in item)) return; if(!('month' in item)) return;

View File

@ -163,7 +163,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
return ''; return '';
}() }()
,'{{# var isSort = !(item2.colGroup) && item2.sort; }}' ,'{{# var isSort = !(item2.colGroup) && item2.sort; }}'
,'<th data-field="{{= item2.field||i2 }}" data-key="{{=d.index}}-{{=i1}}-{{=i2}}" {{# if( item2.parentKey){ }}data-parentkey="{{= item2.parentKey }}"{{# } }} {{# if(item2.minWidth){ }}data-minwidth="{{=item2.minWidth}}"{{# } }} {{# if(item2.maxWidth){ }}data-maxwidth="{{=item2.maxWidth}}"{{# } }} '+ rowCols +' {{# if(item2.unresize || item2.colGroup){ }}data-unresize="true"{{# } }} class="{{# if(item2.hide){ }}layui-hide{{# } }}{{# if(isSort){ }} layui-unselect{{# } }}{{# if(!item2.field){ }} layui-table-col-special{{# } }}"{{# if(item2.title){ }} title="{{ layui.$(\'<div>\' + item2.title + \'</div>\').text() }}"{{# } }}>' ,'<th data-field="{{= item2.field||i2 }}" data-key="{{=d.index}}-{{=i1}}-{{=i2}}" {{# if( item2.parentKey){ }}data-parentkey="{{= item2.parentKey }}"{{# } }} {{# if(item2.minWidth){ }}data-minwidth="{{=item2.minWidth}}"{{# } }} {{# if(item2.maxWidth){ }}data-maxwidth="{{=item2.maxWidth}}"{{# } }} {{# if(item2.style){ }}style="{{=item2.style}}"{{# } }} '+ rowCols +' {{# if(item2.unresize || item2.colGroup){ }}data-unresize="true"{{# } }} class="{{# if(item2.hide){ }}layui-hide{{# } }}{{# if(isSort){ }} layui-unselect{{# } }}{{# if(!item2.field){ }} layui-table-col-special{{# } }}"{{# if(item2.title){ }} title="{{ layui.$(\'<div>\' + item2.title + \'</div>\').text() }}"{{# } }}>'
,'<div class="layui-table-cell laytable-cell-' ,'<div class="layui-table-cell laytable-cell-'
,'{{# if(item2.colGroup){ }}' ,'{{# if(item2.colGroup){ }}'
,'group' ,'group'
@ -584,7 +584,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
lay.style({ lay.style({
target: that.elem[0], target: that.elem[0],
text: text.join(''), text: text.join(''),
id: 'DF-'+ index id: 'DF-table-'+ index
}); });
}; };
@ -1111,7 +1111,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
curr = curr || 1 curr = curr || 1
layui.each(data, function(i1, item1){ layui.each(data, function(i1, item1){
var tds = []; var tds = [];
var tds_fixed = []; var tds_fixed = [];
var tds_fixed_r = []; var tds_fixed_r = [];
var numbers = i1 + options.limit*(curr - 1) + 1; // 序号 var numbers = i1 + options.limit*(curr - 1) + 1; // 序号
@ -1144,34 +1144,31 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
// td 内容 // td 内容
var td = ['<td data-field="'+ field +'" data-key="'+ key +'" '+ function(){ var td = ['<td data-field="'+ field +'" data-key="'+ key +'" '+ function(){
//追加各种属性 // 追加各种属性
var attr = []; var attr = [];
// 是否开启编辑。若 edit 传入函数,则根据函数的返回结果判断是否开启编辑 // 是否开启编辑。若 edit 传入函数,则根据函数的返回结果判断是否开启编辑
(function(edit){ (function(edit){
if(edit) attr.push('data-edit="'+ edit +'"'); // 添加单元格编辑属性标识 if(edit) attr.push('data-edit="'+ edit +'"'); // 添加单元格编辑属性标识
})(typeof item3.edit === 'function' ? item3.edit(item1) : item3.edit); })(typeof item3.edit === 'function' ? item3.edit(item1) : item3.edit);
if(item3.templet) attr.push('data-content="'+ util.escape(content) +'"'); //自定义模板 if(item3.templet) attr.push('data-content="'+ util.escape(content) +'"'); // 自定义模板
if(item3.toolbar) attr.push('data-off="true"'); //行工具列关闭单元格事件 if(item3.toolbar) attr.push('data-off="true"'); // 行工具列关闭单元格事件
if(item3.event) attr.push('lay-event="'+ item3.event +'"'); //自定义事件 if(item3.event) attr.push('lay-event="'+ item3.event +'"'); //自定义事件
if(item3.minWidth) attr.push('data-minwidth="'+ item3.minWidth +'"'); //单元格最小宽度 if(item3.minWidth) attr.push('data-minwidth="'+ item3.minWidth +'"'); // 单元格最小宽度
if(item3.maxWidth) attr.push('data-maxwidth="'+ item3.maxWidth +'"'); //单元格最大宽度 if(item3.maxWidth) attr.push('data-maxwidth="'+ item3.maxWidth +'"'); // 单元格最大宽度
if(item3.style) attr.push('style="'+ item3.style +'"'); // 自定义单元格样式
return attr.join(' '); return attr.join(' ');
}() +' class="'+ function(){ //追加样式 }() +' class="'+ function(){ // 追加样式
var classNames = []; var classNames = [];
if(item3.hide) classNames.push(HIDE); //插入隐藏列样式 if(item3.hide) classNames.push(HIDE); // 插入隐藏列样式
if(!item3.field) classNames.push(ELEM_COL_SPECIAL); //插入特殊列样式 if(!item3.field) classNames.push(ELEM_COL_SPECIAL); // 插入特殊列样式
return classNames.join(' '); return classNames.join(' ');
}() +'">' }() +'">'
,'<div class="layui-table-cell laytable-cell-'+ function(){ //返回对应的CSS类标识 ,'<div class="layui-table-cell laytable-cell-'+ function(){ // 返回对应的CSS类标识
return item3.type === 'normal' ? key return item3.type === 'normal' ? key
: (key + ' laytable-cell-' + item3.type); : (key + ' laytable-cell-' + item3.type);
}() +'"' }() +'"'
+ (item3.align ? ' align="'+ item3.align +'"' : '') + (item3.align ? ' align="'+ item3.align +'"' : '')
+ function(){ +'>'
var attr = [];
if(item3.style) attr.push('style="'+ item3.style +'"'); //自定义单元格样式
return attr.join(' ');
}() +'>'
+ function(){ + function(){
var tplData = $.extend(true, { var tplData = $.extend(true, {
LAY_COL: item3 LAY_COL: item3
@ -1179,7 +1176,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
var checkName = table.config.checkName; var checkName = table.config.checkName;
var disabledName = table.config.disabledName; var disabledName = table.config.disabledName;
//渲染不同风格的列 // 渲染不同风格的列
switch(item3.type){ switch(item3.type){
case 'checkbox': // 复选 case 'checkbox': // 复选
return '<input type="checkbox" name="layTableCheckbox" lay-skin="primary" '+ function(){ return '<input type="checkbox" name="layTableCheckbox" lay-skin="primary" '+ function(){
@ -1211,7 +1208,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
case 'numbers': case 'numbers':
return numbers; return numbers;
//break; //break;
}; }
//解析工具列模板 //解析工具列模板
if(item3.toolbar){ if(item3.toolbar){
@ -1313,6 +1310,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
}, 50); }, 50);
that.haveInit = true; that.haveInit = true;
layer.close(that.tipsIndex);
}; };
table.cache[that.key] = data; //记录数据 table.cache[that.key] = data; //记录数据
@ -1454,6 +1452,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
var attr = []; var attr = [];
if(item3.minWidth) attr.push('data-minwidth="'+ item3.minWidth +'"'); // 单元格最小宽度 if(item3.minWidth) attr.push('data-minwidth="'+ item3.minWidth +'"'); // 单元格最小宽度
if(item3.maxWidth) attr.push('data-maxwidth="'+ item3.maxWidth +'"'); // 单元格最小宽度 if(item3.maxWidth) attr.push('data-maxwidth="'+ item3.maxWidth +'"'); // 单元格最小宽度
if(item3.style) attr.push('style="'+ item3.style +'"'); // 自定义单元格样式
return attr.join(' '); return attr.join(' ');
}() +' class="'+ function(){ // 追加样式 }() +' class="'+ function(){ // 追加样式
var classNames = []; var classNames = [];
@ -1468,7 +1467,6 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
}() +'"'+ function(){ }() +'"'+ function(){
var attr = []; var attr = [];
if(item3.align) attr.push('align="'+ item3.align +'"'); // 对齐方式 if(item3.align) attr.push('align="'+ item3.align +'"'); // 对齐方式
if(item3.style) attr.push('style="'+ item3.style +'"'); // 自定义单元格样式
return attr.join(' '); return attr.join(' ');
}() +'>' + function(){ }() +'>' + function(){
var totalRow = item3.totalRow || options.totalRow; var totalRow = item3.totalRow || options.totalRow;
@ -1773,7 +1771,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
//获取滚动条宽度 //获取滚动条宽度
Class.prototype.getScrollWidth = function(elem){ Class.prototype.getScrollWidth = function(elem){
var width = 0; var width;
if(elem){ if(elem){
width = elem.offsetWidth - elem.clientWidth; width = elem.offsetWidth - elem.clientWidth;
} else { } else {
@ -1793,19 +1791,19 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
Class.prototype.scrollPatch = function(){ Class.prototype.scrollPatch = function(){
var that = this; var that = this;
var layMainTable = that.layMain.children('table'); var layMainTable = that.layMain.children('table');
var scollWidth = that.layMain.width() - that.layMain.prop('clientWidth'); // 纵向滚动条宽度 var scrollWidth = that.layMain.width() - that.layMain.prop('clientWidth'); // 纵向滚动条宽度
var scollHeight = that.layMain.height() - that.layMain.prop('clientHeight'); // 横向滚动条高度 var scrollHeight = that.layMain.height() - that.layMain.prop('clientHeight'); // 横向滚动条高度
var getScrollWidth = that.getScrollWidth(that.layMain[0]); // 获取主容器滚动条宽度,如果有的话 var getScrollWidth = that.getScrollWidth(that.layMain[0]); // 获取主容器滚动条宽度,如果有的话
var outWidth = layMainTable.outerWidth() - that.layMain.width(); // 表格内容器的超出宽度 var outWidth = layMainTable.outerWidth() - that.layMain.width(); // 表格内容器的超出宽度
// 添加补丁 // 添加补丁
var addPatch = function(elem){ var addPatch = function(elem){
if(scollWidth && scollHeight){ if(scrollWidth && scrollHeight){
elem = elem.eq(0); elem = elem.eq(0);
if(!elem.find('.layui-table-patch')[0]){ if(!elem.find('.layui-table-patch')[0]){
var patchElem = $('<th class="layui-table-patch"><div class="layui-table-cell"></div></th>'); // 补丁元素 var patchElem = $('<th class="layui-table-patch"><div class="layui-table-cell"></div></th>'); // 补丁元素
patchElem.find('div').css({ patchElem.find('div').css({
width: scollWidth width: scrollWidth
}); });
elem.find('tr').append(patchElem); elem.find('tr').append(patchElem);
} }
@ -1819,7 +1817,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
// 固定列区域高度 // 固定列区域高度
var mainHeight = that.layMain.height(); var mainHeight = that.layMain.height();
var fixHeight = mainHeight - scollHeight; var fixHeight = mainHeight - scrollHeight;
that.layFixed.find(ELEM_BODY).css( that.layFixed.find(ELEM_BODY).css(
'height', 'height',
@ -1834,7 +1832,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
](HIDE); ](HIDE);
// 操作栏 // 操作栏
that.layFixRight.css('right', scollWidth - 1); that.layFixRight.css('right', scrollWidth - 1);
}; };
// 事件处理 // 事件处理
@ -1878,6 +1876,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
layui.stope(e); layui.stope(e);
_DOC.trigger('table.tool.panel.remove'); _DOC.trigger('table.tool.panel.remove');
layer.close(that.tipsIndex);
switch(events){ switch(events){
case 'LAYTABLE_COLS': // 筛选列 case 'LAYTABLE_COLS': // 筛选列
@ -1973,7 +1972,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
printWin.document.write(style + html.prop('outerHTML')); printWin.document.write(style + html.prop('outerHTML'));
printWin.document.close(); printWin.document.close();
if(layui.device('edg').edg){ if(layui.device('edg').edg){
printWin.onafterprint = printWin.close; printWin.onafterprint = printWin.close;
printWin.print(); printWin.print();
@ -2072,6 +2071,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
dict.rule.style.width = setWidth + 'px'; dict.rule.style.width = setWidth + 'px';
thatTable.setGroupWidth(thisTable.eventMoveElem); thatTable.setGroupWidth(thisTable.eventMoveElem);
layer.close(that.tipsIndex);
} }
} }
}).on('mouseup', function(e){ }).on('mouseup', function(e){
@ -2319,7 +2319,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
].join(','); ].join(',');
if( $(e.target).is(UNROW) || $(e.target).closest(UNROW)[0]){ if( $(e.target).is(UNROW) || $(e.target).closest(UNROW)[0]){
return; return;
}; }
setRowEvent.call(this, 'row'); setRowEvent.call(this, 'row');
}).on('dblclick', 'tr', function(){ // 双击行 }).on('dblclick', 'tr', function(){ // 双击行
setRowEvent.call(this, 'rowDouble'); setRowEvent.call(this, 'rowDouble');
@ -2463,44 +2463,75 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
var elemCell = td.children(ELEM_CELL); var elemCell = td.children(ELEM_CELL);
var ELEM_CELL_C = 'layui-table-cell-c'; var ELEM_CELL_C = 'layui-table-cell-c';
var elemCellClose = $('<i class="layui-icon layui-icon-up '+ ELEM_CELL_C +'">'); var elemCellClose = $('<i class="layui-icon layui-icon-up '+ ELEM_CELL_C +'">');
var expandedMode = col.expandedMode || options.cellExpandedMode;
// 恢复其他已经展开的单元格 // 展开风格
that.elem.find('.'+ ELEM_CELL_C).trigger('click'); if (expandedMode === 'tips') { // TIPS 展开风格
that.tipsIndex = layer.tips([
// 设置当前单元格展开宽度 '<div class="layui-table-tips-main" style="margin-top: -'+ (elemCell.height() + 23) +'px;'+ function(){
that.cssRules(key, function(item){ if(options.size === 'sm'){
var width = item.style.width; return 'padding: 4px 15px; font-size: 12px;';
var expandedWidth = col.expandedWidth || (that.elem.width() / 3); }
if(options.size === 'lg'){
// 展开后的宽度不能小于当前宽度 return 'padding: 14px 15px;';
if(expandedWidth < parseFloat(width)) expandedWidth = parseFloat(width); }
return '';
elemCellClose.data('cell-width', width); }() +'">',
item.style.width = expandedWidth + 'px'; elemCell.html(),
'</div>',
setTimeout(function(){ '<i class="layui-icon layui-table-tips-c layui-icon-close"></i>'
that.scrollPatch(); // 滚动条补丁 ].join(''), elemCell[0], {
tips: [3, ''],
time: -1,
anim: -1,
maxWidth: (device.ios || device.android) ? 300 : that.elem.width()/2,
isOutAnim: false,
skin: 'layui-table-tips',
success: function(layero, index){
layero.find('.layui-table-tips-c').on('click', function(){
layer.close(index);
});
}
}); });
}); } else { // 多行展开风格
// 恢复其他已经展开的单元格
that.elem.find('.'+ ELEM_CELL_C).trigger('click');
// 设置当前单元格展开样式 // 设置当前单元格展开宽度
that.setRowActive(index, ELEM_EXPAND);
// 插入关闭按钮
if(!elemCell.next('.'+ ELEM_CELL_C)[0]){
elemCell.after(elemCellClose);
}
// 关闭展开状态
elemCellClose.on('click', function(){
var $this = $(this);
that.setRowActive(index, ELEM_EXPAND, true); // 移除单元格展开样式
that.cssRules(key, function(item){ that.cssRules(key, function(item){
item.style.width = $this.data('cell-width'); // 恢复单元格展开前的宽度 var width = item.style.width;
that.resize(); // 滚动条补丁 var expandedWidth = col.expandedWidth || options.cellExpandedWidth;
// 展开后的宽度不能小于当前宽度
if(expandedWidth < parseFloat(width)) expandedWidth = parseFloat(width);
elemCellClose.data('cell-width', width);
item.style.width = expandedWidth + 'px';
setTimeout(function(){
that.scrollPatch(); // 滚动条补丁
});
}); });
$this.remove();
}); // 设置当前单元格展开样式
that.setRowActive(index, ELEM_EXPAND);
// 插入关闭按钮
if(!elemCell.next('.'+ ELEM_CELL_C)[0]){
elemCell.after(elemCellClose);
}
// 关闭展开状态
elemCellClose.on('click', function(){
var $this = $(this);
that.setRowActive(index, ELEM_EXPAND, true); // 移除单元格展开样式
that.cssRules(key, function(item){
item.style.width = $this.data('cell-width'); // 恢复单元格展开前的宽度
that.resize(); // 滚动条补丁
});
$this.remove();
});
}
othis.remove(); othis.remove();
layui.stope(e); layui.stope(e);
@ -2803,6 +2834,20 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
if(device.ie) return hint.error('IE_NOT_SUPPORT_EXPORTS'); if(device.ie) return hint.error('IE_NOT_SUPPORT_EXPORTS');
// 处理 treeTable 数据
if (config.tree && config.tree.view) {
try {
data = $.extend(true, [], table.cache[id]);
data = (function fn(data) {
return data.reduce(function (acc, obj){
var children = obj.children || [];
delete obj.children;
return acc.concat(obj, fn(children));
}, []);
})(Array.from(data));
} catch (e) {}
}
alink.href = 'data:'+ textType +';charset=utf-8,\ufeff'+ encodeURIComponent(function(){ alink.href = 'data:'+ textType +';charset=utf-8,\ufeff'+ encodeURIComponent(function(){
var dataTitle = []; var dataTitle = [];
var dataMain = []; var dataMain = [];
@ -2984,5 +3029,3 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
exports(MOD_NAME, table); exports(MOD_NAME, table);
}); });

View File

@ -52,6 +52,7 @@ layui.define(['lay','layer'], function(exports){
var ELEM_IFRAME = 'layui-upload-iframe'; var ELEM_IFRAME = 'layui-upload-iframe';
var ELEM_CHOOSE = 'layui-upload-choose'; var ELEM_CHOOSE = 'layui-upload-choose';
var ELEM_DRAG = 'layui-upload-drag'; var ELEM_DRAG = 'layui-upload-drag';
var UPLOADING = 'UPLOADING';
// 构造器 // 构造器
var Class = function(options){ var Class = function(options){
@ -87,7 +88,7 @@ layui.define(['lay','layer'], function(exports){
}; };
// 初始渲染 // 初始渲染
Class.prototype.render = function(options){ Class.prototype.render = function(){
var that = this; var that = this;
var options = that.config; var options = that.config;
@ -218,16 +219,37 @@ layui.define(['lay','layer'], function(exports){
var request = function(sets){ var request = function(sets){
var formData = new FormData(); var formData = new FormData();
// 删除正在上传中的文件队列
var removeUploaded = function(index, file) {
if (file[UPLOADING]) {
delete items[index];
return true;
}
};
// 追加额外的参数 // 追加额外的参数
layui.each(options.data, function(key, value){ layui.each(options.data, function(key, value){
value = typeof value === 'function' ? value() : value; value = typeof value === 'function' ? value() : value;
formData.append(key, value); formData.append(key, value);
}); });
// 添加 file 到表单域 /*
sets.unified ? layui.each(items, function(index, file){ *添加 file 到表单域
formData.append(options.field, file); */
}) : formData.append(options.field, sets.file);
// 是否统一上传
if (sets.unified) {
layui.each(items, function(index, file){
if (removeUploaded(index, file)) return;
file[UPLOADING] = true;
formData.append(options.field, file);
});
} else { // 逐一上传
if (removeUploaded(sets.index, sets.file)) return;
formData.append(options.field, sets.file);
}
sets.file[UPLOADING] = true; // 上传中的标记
// ajax 参数 // ajax 参数
var opts = { var opts = {
@ -236,7 +258,6 @@ layui.define(['lay','layer'], function(exports){
data: formData, data: formData,
contentType: false, contentType: false,
processData: false, processData: false,
// dataType: 'json',
headers: options.headers || {}, headers: options.headers || {},
success: function(res){ // 成功回调 success: function(res){ // 成功回调
options.unified ? (successful += that.fileLength) : successful++; options.unified ? (successful += that.fileLength) : successful++;
@ -253,6 +274,12 @@ layui.define(['lay','layer'], function(exports){
allDone(); allDone();
} }
}; };
// dataType
if (options.dataType) {
opts.dataType = options.dataType;
} else if (options.force === 'json') {
opts.dataType = options.force;
}
// 进度条 // 进度条
if(typeof options.progress === 'function'){ if(typeof options.progress === 'function'){
opts.xhr = function(){ opts.xhr = function(){
@ -493,17 +520,17 @@ layui.define(['lay','layer'], function(exports){
send(); send();
}; };
//重置方法 // 重置方法
Class.prototype.reload = function(options){ Class.prototype.reload = function(opts){
options = options || {}; opts = opts || {};
delete options.elem; delete opts.elem;
delete options.bindAction; delete opts.bindAction;
var that = this; var that = this;
var options = that.config = $.extend({}, that.config, upload.config, options); var options = that.config = $.extend({}, that.config, upload.config, opts);
var next = options.elem.next(); var next = options.elem.next();
//更新文件域相关属性 // 更新文件域相关属性
next.attr({ next.attr({
name: options.name, name: options.name,
accept: options.acceptMime, accept: options.acceptMime,