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

View File

@ -1,6 +1,6 @@
### 😃 本次 PR 的变化性质
> 请至少勾选一项[ ] 内填写 x
> 请至少勾选一项
- [ ] 功能新增
- [x] 问题修复
@ -15,9 +15,8 @@
### ✅ 本次 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` 不可见状态,且依旧占用空间 |
<h2 id="edge" lay-toc="{}">三角实体</h2>
<h2 id="triangle" lay-toc="{}">三角实体</h2>
| className | 描述 |
| --- | --- |
@ -66,6 +66,21 @@ toc: true
</textarea>
</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>
@ -167,4 +182,4 @@ toc: true
</body>
</html>
</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>array</td>
@ -147,12 +159,12 @@ tools: ['full', 'window']
<td>toolsEvent <sup>2.8+</sup></td>
<td>
点击工具栏的回调函数,函数返回 `tools` 设置的名称,如:
点击工具栏的回调函数,功能同 `tools` 中的 `event`,只是需通过 `type` 属性来区分是哪个工具菜单。
```
toolsEvent: function(othis, type){
console.log(othis); // 当前图标元素对象
console.log(type); // tools 中设置的对应值
toolsEvent: function(obj){
console.log(obj); // 当前实例相关信息
console.log(obj.type); // 当前实例相关信息
}
```
@ -197,7 +209,7 @@ text: {
<td>header <sup>2.8+</sup></td>
<td>
是否开启 Code 栏头部区域
是否开启 Code 栏头部区域
</td>
<td>boolean</td>
@ -208,16 +220,6 @@ text: {
</td>
</tr>
<tr>
<td>about</td>
<td>
设置 Code 栏头部右上角信息。必须开启 `header` 属性后有效。
</td>
<td>string</td>
<td>-</td>
</tr>
<tr>
<td>ln</td>
<td>
@ -232,10 +234,10 @@ text: {
</td>
</tr>
<tr>
<td>skin</td>
<td>theme <sup>2.8.17+</sup></td>
<td>
Code 容器的风格,可选值有:
Code 容器的主题风格,可选值有:
- `light` 浅色模式(默认)
- `dark` 深色模式
@ -256,6 +258,84 @@ Code 容器的风格,可选值有:
`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>
</tr>
<tr>
@ -288,7 +368,7 @@ done: function(obj){
<td colspan="3">
<div id="options.onCopy" lay-pid="options" class="ws-anchor">
点击复制图标时的回调函数。 该回调一旦设定,则不再执行内置的复制操作。
点击复制图标时的回调函数。
</div>
```
@ -300,4 +380,4 @@ onCopy: function(code){
</td>
</tr>
</tbody>
</table>
</table>

View File

@ -10,18 +10,37 @@ toc: true
<h2 id="api" lay-toc="{}">方法</h2>
`layui.code(options);`
`var codeInst = layui.code(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>
<pre class="layui-code code-demo" lay-options="{}">
// 在里面放置任意的 code
test
test
light theme
light theme
light theme
</pre>
<hr>
<pre class="layui-code code-demo" lay-options="{theme: 'dark'}">
dark theme
dark theme
dark theme
</pre>
<!-- import layui -->
@ -40,4 +59,8 @@ layui.use(function(){
<div>
{{- d.include("/code/detail/options.md") }}
</div>
</div>
<h2>小贴士</h2>
> code 组件可广泛应用于技术类文档、博客等页面,可轻松适配第三方主流语法高亮器。

View File

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

View File

@ -111,7 +111,7 @@ form 还可以借助*栅格*实现更灵活的响应式布局。
| --- | --- | --- |
| title | 自定义 | 设置表单元素标题,一般用于 `checkbox,radio` 元素 |
| 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-reqtext | 自定义 | 设置*必填项*`lay-verify="required"`)的默认提示文本 |
| lay-affix | [#详见](input.html#affix) | 输入框动态点缀,`<input type="text">`元素 **私有属性** |
@ -408,7 +408,6 @@ form.on('select(test)', function(data){
| 属性名 | 描述 | 类型 | 默认值 |
| --- | --- | --- | --- |
| autocomplete | 设置 input 框的 `autocomplete` 属性初始值 | string | - |
| verIncludeRequired <sup>2.8.4+</sup> | 验证规则中是否同时包含必填。 form 组件在 `2.8.3` 版本中调整了内置校验规则,即:仅当非空时进行校验,避免强制携带必填的校验规则。如需保留之前的验证规则(即同时校验必填),可将该属性设置为 `true`。但一般还是建议将必填项放置在 `lay-verify` 属性上,如: `lay-verify="required\|number"` | boolean | `false` |
该方法用于对 form 组件进行全局设置。

View File

@ -109,12 +109,12 @@ npm i layui
点击上方 `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://github.com/Sight-wcg/layui-theme-dark" target="_blank">深色主题</a> (社区贡献)
- <a href="https://layui.dev/playground/2/">在线测试</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>
</pre>
<div class="ws-docs-showcase" style="margin-top: 16px;"></div>
<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']}">
@ -98,4 +100,4 @@
### 小贴士
> 事实上 layer 丰富的基础属性,可足够让您的弹出层变得千变万化,为了避免占用太多篇幅,就不做过多演示了。
> 事实上 layer 丰富的基础属性,可足够让您的弹出层变得千变万化,为了避免占用太多篇幅,就不做过多演示了。

View File

@ -64,7 +64,7 @@ layui.use(function(){
{
"alt": "浩瀚宇宙",
"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",
"pid": 1,
"src": "https://unpkg.com/outeres/demo/layer.png",
"src": "https://unpkg.com/outeres@0.1.1/demo/layer.png",
},
{
"alt": "壁纸",
"pid": 3,
"src": "https://unpkg.com/outeres/demo/000.jpg",
"src": "https://unpkg.com/outeres@0.1.1/demo/000.jpg",
},
{
"alt": "浩瀚宇宙",
"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",
"pid": 1,
"src": "https://unpkg.com/outeres/demo/layer.png",
"src": "https://unpkg.com/outeres@0.1.1/demo/layer.png",
},
{
"alt": "壁纸",
"pid": 3,
"src": "https://unpkg.com/outeres/demo/000.jpg",
"src": "https://unpkg.com/outeres@0.1.1/demo/000.jpg",
},
{
"alt": "浩瀚宇宙",
"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>
</tr>
<tr>
<td>expandedWidth <sup>2.8.14+</sup></td>
<td>expandedWidth <sup>2.8.15+</sup></td>
<td>
设置单元格被展开后的宽度,默认取表格容器的三分之一宽度。若设置的值的小于当前列宽,则展开后的列宽保持不变。
设置单元格被展开后的宽度。若设置的值的小于当前列宽,则展开后的列宽保持不变。注:当 `expandedMode` 属性为默认值时有效。
</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>
</tr>
<tr>
@ -467,4 +482,4 @@ edit: function(d){
</td>
</tr>
</tbody>
</table>
</table>

View File

@ -188,6 +188,33 @@
<td>-</td>
</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>是否开启对内容的编码(转义 html</td>
<td>boolean</td>
@ -390,10 +417,28 @@ initSort: {
</td>
</tr>
<tr>
<td>before <sup>2.7+</sup></td>
<td>数据渲染之前的回调函数。</td>
<td>function</td>
<td>-</td>
<td>
[before](#options.before) <sup>2.7+</sup>
</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>
<td>
@ -401,7 +446,7 @@ initSort: {
[done](#options.done)
</td>
<td>
<td colspan="3">
<div class="ws-anchor" id="options.done">
数据渲染完毕的回调函数。返回的参数如下:
@ -414,20 +459,26 @@ table.render({
console.log(curr); // 得到当前页码
console.log(count); // 得到数据总量
console.log(origin); // 回调函数所执行的来源 --- 2.8.7+
}
},
// … // 其它属性
});
```
</td>
<td>function</td>
<td>-</td>
</tr>
<tr>
<td>error <sup>2.6+</sup></td>
<td> 数据请求失败的回调函数。返回两个参数:错误对象、内容。</td>
<td>function</td>
<td>-</td>
<td colspan="3">
数据请求失败的回调函数。返回两个参数:错误对象、内容。
```
error: function(e, msg) {
console.log(e, msg)
}
```
</td>
</tr>
</tbody>
</table>
</table>

View File

@ -55,7 +55,7 @@ layui.use(['table', 'dropdown'], function(){
// 创建渲染实例
table.render({
elem: '#test',
url:'/static/2.8/json/table/demo1.json', // 此处为静态模拟数据,实际使用时需换成真实接口
url: '/static/2.8/json/table/demo1.json', // 此处为静态模拟数据,实际使用时需换成真实接口
toolbar: '#toolbarDemo',
defaultToolbar: ['filter', 'exports', 'print', {
title: '提示',
@ -73,7 +73,7 @@ layui.use(['table', 'dropdown'], function(){
{type: 'checkbox', fixed: 'left'},
{field:'id', fixed: 'left', width:80, title: 'ID', sort: true, totalRowText: '合计:'},
{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:'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 }} 😊!}}'},

View File

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

View File

@ -90,6 +90,16 @@ data: {
</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>
</tr>
<tr>
@ -470,4 +480,4 @@ error: function(index, upload){
</td>
</tr>
</tbody>
</table>
</table>

View File

@ -11,6 +11,8 @@ toc: true
以下示例的部分上传接口由第三方网站 `https://httpbin.org` 提供,它可以模拟各类 HTTP 请求。若未配置上传接口的,每次上传都会报「请求上传接口出现异常」的提示,这属于正常现象。
<div class="ws-docs-showcase"></div>
<div>
{{- d.include("/upload/detail/demo.md") }}
</div>
@ -122,4 +124,4 @@ inst.reload({
- 自建上传服务。在服务端配置 `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)
<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">
2.8.16
@ -31,7 +68,7 @@ toc: true
- 修复 `data` 模式下排序之后出现节点结构错乱的问题 # 1358/I7TXXL
- 优化 `data.cascade` 属性,新增 `none` 可选值,即操作节点时不做任何联动 # 1358
- 优化 数据项为禁用状态时的全选复选框的状态 # 1329
- 优化 异步加载节点为空时的展开状态 # 1326
- 优化 异步加载节点为空时的展开状态 # 1326
- #### laydate
- 优化 `shortcuts.value` 快捷选项的赋值属性,支持函数类型 # 1324
- #### rate

View File

@ -8,32 +8,67 @@
<link href="../src/css/layui.css" rel="stylesheet">
<style>
body{padding: 32px;}
pre{margin-bottom: 20px;}
pre{margin: 16px 0;}
</style>
</head>
<body>
<pre class="layui-code" lay-height="300px">
// 在里面存放任意的文本内容
code line
code line
code line
code line
code line
code line
code line
code line
code line
code line
code line
code line
code line
code line
code line
code line
code line
<pre id="test" class="layui-test">
<textarea class="layui-hide">
<div class="layui-btn-container">
<button type="button" class="layui-btn">默认按钮</button>
</div>
<p class="layui-padding-3">
AaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaA
</p>
<div class="layui-btn-container">
<button class="layui-btn layui-btn-primary layui-border-green">主色按钮</button>
</div>
<script type="text/html">
<h3>{{= d.title }}</h3>
<ul>
{{# layui.each(d.list, function(index, item){ }}
<li>
<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><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}">
code line
code line
@ -101,33 +136,137 @@ code line
</div>
</pre>
<pre class="layui-code" lay-about="code">
<pre class="layui-code" lay-options="{about: 'About info'}">
About
</pre>
<pre id="custom1">
custom more about
</pre>
<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>
layui.use('code', function(){
// 通用实例,根据元素属性定制化参数
layui.code({
//about: 'code' // 右上角默认显示 code
tools: ['tips'],
preview: true
layui.use(['code', 'dropdown'], function(){
var dropdown = layui.dropdown;
var $ = layui.$;
// return;
// 高亮主题 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({
elem: '#custom1',
about: [
'<a href="javascript:;">复制</a>',
'<a href="about:blank" target="_blank">跳转</a>'
].join('')
})
elem: '.layui-code',
tools: ['tips'],
langMarker: true,
lang: 'html',
// preview: true
});
});
</script>
</body>

View File

@ -170,7 +170,7 @@
<div class="layui-form-item">
<label class="layui-form-label">邮箱</label>
<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 class="layui-form-item">
@ -200,7 +200,7 @@
<div class="layui-inline">
<label class="layui-form-label">行内表单</label>
<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="0">你工"作"的 第一个城市</option>
<option value="1" disabled>你的工号</option>
@ -380,19 +380,23 @@
var util = layui.util;
var laydate = layui.laydate;
//自定义验证规则
// 自定义验证规则
form.verify({
title: function(value){
if(value.length < 5){
if(value && value.length < 5){ //
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": {
"checkin": "777"
}
,"data1": []
,"data": [{
"id": "10001"
,"username": "杜甫123"
@ -129,4 +130,4 @@
,"checkin": "106"
,"joinTime": "2016-10-14"
}]
}
}

View File

@ -174,38 +174,44 @@ layui.use('laydate', function(laydate){
});
//范围选择1
// 范围选择1
laydate.render({
elem: '#test1' //指定元素
,type: 'datetime'
,trigger: 'click'
//,lang: 'en'
//,theme: 'grid'
,range: true //开启日期范围,默认使用“-”分割
//,min: '1970-1-1'
//,max: '2021-5-9'
//,value: '2021-05-09 12:06:09'
//,value: '2021-05-08 - 2021-03-27'
,done: function(value, date, endDate){
elem: '#test1', // 指定元素
type: 'datetime',
trigger: 'click',
// lang: 'en',
// theme: 'grid',
range: true, // 开启日期范围,默认使用“-”分割
// rangeLinked: true,
// min: '1970-1-1',
// max: '2021-5-9',
// value: '2021-05-09 12:06:09',
// value: '2021-05-08 - 2021-03-27',
done: function(value, date, endDate){
console.log(value, date, endDate);
//this.elem.val(123);
}
,change: function(value, date, endDate){
},
change: function(value, date, endDate){
console.log(value, date, endDate);
}
});
//return;
// return;
//范围选择2
// 范围选择2
laydate.render({
elem: '#test1-2'
,type: 'date'
,range: ['#test-startDate-1', '#test-endDate-1']
,rangeLinked: true // 是否开启日期范围选择时的区间联动标注模式
//,value: ['2022-05-01', '2022-06-01']
//,value: '2022-05-01 - 2022-06-01'
elem: '#test1-2',
type: 'date',
range: ['#test-startDate-1', '#test-endDate-1'],
rangeLinked: true, // 是否开启日期范围选择时的区间联动标注模式
// value: ['2022-05-01', '2022-10-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>
</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">
更多测试
<i class="layui-icon layui-icon-down layui-font-12"></i>
@ -75,12 +77,12 @@
<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>
(function(off){
if(!off) return;
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
});
//渲染
// 渲染
window.ins1 = table.render({
elem: '#test',
height: 520,
@ -153,15 +155,17 @@ layui.use(['table', 'dropdown'], function(){
// escape: false,
editTrigger: 'dblclick',
// cellMaxWidth: 320
// cellExpandedWidth: 160, // 单元格默认展开后的宽度
// cellExpandedStyle: 'tips', // 单元格默认展开风格
cols: !1 ? test_cols : [[
{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:'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;
}, templet: '#usernameTpl'},
{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>'
}},
{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
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:'ip', title:'IP', width: 120, align: 'right'},
{field:'checkin', title:'打卡', width: 100, sort: true, totalRow: '{{= d.TOTAL_ROW.checkin }} 次'},
@ -256,7 +260,7 @@ layui.use(['table', 'dropdown'], function(){
// 重载测试
dropdown.render({
elem: '#reloadTest', //可绑定在任意元素中,此处以上述按钮为例
elem: '#reloadTest', // 可绑定在任意元素中,此处以上述按钮为例
data: [{
id: 'reload',
title: '重载'
@ -336,10 +340,9 @@ layui.use(['table', 'dropdown'], function(){
}
});
// 更多测试
dropdown.render({
elem: '#moreTest', //可绑定在任意元素中,此处以上述按钮为例
elem: '#moreTest', // 可绑定在任意元素中,此处以上述按钮为例
data: [{
id: 'add',
title: '添加'
@ -385,8 +388,8 @@ layui.use(['table', 'dropdown'], function(){
/*
request: { // 自定义请求参数名称
pageName: 'curr', //页码的参数名称默认page
limitName: 'nums' //每页数据量的参数名默认limit
pageName: 'curr', // 页码的参数名称默认page
limitName: 'nums' // 每页数据量的参数名默认limit
},
parseData: function(res){ // 任意数据格式的解析
return {
@ -403,20 +406,20 @@ layui.use(['table', 'dropdown'], function(){
}
});
//排序事件
// 排序事件
table.on('sort(test)', function(obj){
//console.log(obj);
// console.log(obj);
//return;
// return;
layer.msg('服务端排序。order by '+ obj.field + ' ' + obj.type);
//服务端排序
// 服务端排序
table.reloadData('test', {
//initSort: obj,
//page: {curr: 1}, //重新从第一页开始
// initSort: obj,
// page: {curr: 1}, // 重新从第一页开始
where: { // 向服务端传入排序参数
key: obj.field, //排序字段
order: obj.type //排序方式
key: obj.field, // 排序字段
order: obj.type // 排序方式
}
});
});
@ -430,18 +433,31 @@ layui.use(['table', 'dropdown'], function(){
case 'getCheckData':
var data = checkStatus.data;
layer.alert(layui.util.escape(JSON.stringify(data)));
break;
break;
case 'getData':
var getData = table.getData(id);
console.log(getData);
layer.alert(layui.util.escape(JSON.stringify(getData)));
break;
break;
case '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':
layer.alert('Table for layui-v'+ layui.v);
break;
break;
};
});
@ -450,16 +466,11 @@ layui.use(['table', 'dropdown'], function(){
console.log(obj);
});
//触发单元格工具事件
// 触发单元格工具事件
table.on('tool(test)', function(obj){ // 双击 toolDouble
var data = obj.data;
//console.log(obj)
if(obj.event === 'del'){
layer.confirm('真的删除行么', function(index){
obj.del();
layer.close(index);
});
} else if(obj.event === 'edit'){
// console.log(obj)
if (obj.event === 'edit') {
layer.prompt({
formType: 2
,value: data.email
@ -477,17 +488,20 @@ layui.use(['table', 'dropdown'], function(){
*/
layer.close(index);
});
} else if (obj.event === 'del') {
layer.confirm('真的删除行么', function(index){
obj.del();
layer.close(index);
});
}
});
//触发表格复选框选择
// 触发表格复选框选择
table.on('checkbox(test)', function(obj){
console.log(obj)
});
//触发表格单选框选择
// 触发表格单选框选择
table.on('radio(test)', function(obj){
console.log(obj)
});

View File

@ -13,6 +13,12 @@
<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>
layui.use(['treeTable'], function(){
@ -23,6 +29,7 @@ layui.use(['treeTable'], function(){
elem: '#test',
url: './json/treeTable/demo-1.json',
maxHeight: 'full-32',
toolbar: '#TPL-treeTable-demo',
tree: {
customName: {
name: 'name'

View File

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

View File

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

View File

@ -513,12 +513,37 @@ a cite{font-style: normal; *cursor:pointer;}
.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-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-field-title{margin: 16px 0; border-width: 0; border-top-width: 1px;}
.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):hover{text-decoration: underline;}
.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-13{font-size: 13px !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-32{font-size: 32px !important;}
/* 字体颜色 */
.layui-font-red{color: #ff5722 !important;} /*赤*/
.layui-font-orange{color: #ffb800!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: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 .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:first-child{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-up{top: 0; border-bottom: 1px solid #eee;}
.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[type="number"]::-webkit-outer-spin-button,
.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:hover{background-color: #fbfbfb;}
/* 单元格多行展开风格 */
.layui-table-expanded{height: 95px;}
.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-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 > * {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-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 .layui-nav-itemed>a{color: #000 !important;}
.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-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,

View File

@ -2,59 +2,71 @@
* 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-title{position: relative; padding: 0 10px; height: 40px; line-height: 40px; border-bottom: 1px solid #eee; font-size: 12px;}
.layui-code-title > .layui-code-about{position: absolute; right: 10px; top: 0; color: #B7B7B7;}
.layui-code-about > a{padding-left: 10px;}
.layui-code-view > .layui-code-ol,
.layui-code-view > .layui-code-ul{max-height: 100%; padding: 0 !important; position: relative; overflow: auto;}
.layui-code-view > .layui-code-ol > li{position: relative; margin-top: 0 !important; margin-left: 45px !important; line-height: 20px; padding: 0 10px !important; border-left: 1px solid #e2e2e2; list-style-type: decimal-leading-zero; *list-style-type: decimal; background-color: #fff;}
.layui-code-view > .layui-code-ol > li:first-child,
.layui-code-view > .layui-code-ul > li:first-child{padding-top: 10px !important;}
.layui-code-view > .layui-code-ol > li:last-child,
.layui-code-view > .layui-code-ul > li:last-child{padding-bottom: 10px !important;}
.layui-code-view > .layui-code-ul > li{position: relative; line-height: 20px; padding: 0 10px !important; list-style-type: none; *list-style-type: none; background-color: #fff;}
.layui-code-view pre{margin: 0;}
/* 字体 */
.layui-code-wrap{font-size: 13px; font-family: "Courier New",Consolas,"Lucida Console";}
/* 基础结构 */
.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 pre{margin: 0 !important;}
.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-header > .layui-code-header-about{position: absolute; right: 11px; top: 0; color: #B7B7B7;}
.layui-code-header-about > a{padding-left: 10px;}
.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-line{position: relative; line-height: 19px; margin: 0 !important;}
.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-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 > .layui-tab-title{border-bottom: none;}
.layui-code-preview > .layui-code > .layui-code-title{display: none;}
.layui-code-preview > .layui-tab > .layui-tab-title{border-width: 0;}
.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 > 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.layui-icon-file-b{color: #999;}
.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 .layui-code-item{width: 100% !important; border-width: 0 !important; border-top-width: 1px !important;}
.layui-code-full .layui-code-item,
.layui-code-full .layui-code-ol,
.layui-code-full .layui-code-ul{height: calc(100vh - 51px) !important; box-sizing: border-box;}
.layui-code-full .layui-code-view,
.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(){
this.v = '2.8.16'; // Layui 版本号
this.v = '2.8.17'; // Layui 版本号
};
// 识别预先可能定义的指定全局对象

View File

@ -1,32 +1,38 @@
/**
* code
* code
* Code 预览组件
*/
layui.define(['lay', 'util', 'element', 'form'], function(exports){
"use strict";
var $ = layui.$;
var util = layui.util;
var element = layui.element;
var form = layui.form;
var layer = layui.layer;
var hint = layui.hint();
// 常量
var CONST = {
ELEM_VIEW: 'layui-code-view',
ELEM_COPY: 'layui-code-copy',
ELEM_TAB: 'layui-tab',
ELEM_TITLE: 'layui-code-title',
ELEM_HEADER: 'layui-code-header',
ELEM_FULL: 'layui-code-full',
ELEM_PREVIEW: 'layui-code-preview',
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 = {
elem: '.layui-code', // 元素选择器
elem: '', // 元素选择器
about: '', // 代码栏右上角信息
ln: true, // 代码区域是否显示行号
header: false, // 是否显示代码栏头部区域
@ -35,345 +41,562 @@ layui.define(['lay', 'util', 'element', 'form'], function(exports){
// 默认文本
text: {
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){
return $.trim(str).replace(/^\n|\n$/, '');
return trimEnd(str).replace(/^\n|\n$/, '');
};
// export api
exports('code', function(options){
var opts = options = $.extend(true, {}, config, options);
exports('code', function(options, mode){
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);
if(!options.elem[0]) return;
var othis = options.elem = $(options.elem);
if(!othis[0]) return ret;
// 从内至外渲染
layui.each(options.elem.get().reverse(), function(index, item){
var othis = $(item);
// 合并属性上的参数,并兼容旧版本属性写法 lay-*
var options = $.extend(true, {}, opts, lay.options(item), function(obj){
var attrs = ['title', 'height', 'encode', 'skin', 'about'];
layui.each(attrs, function(i, attr){
var value = othis.attr('lay-'+ attr);
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()));
// 合并属性上的参数,并兼容旧版本属性写法 lay-*
$.extend(true, options, lay.options(othis[0]), function(obj){
var attrs = ['title', 'height', 'encode', 'skin', 'about'];
layui.each(attrs, function(i, attr){
var value = othis.attr('lay-'+ attr);
if(typeof value === 'string'){
obj[attr] = value;
}
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
if(typeof options.codeParse === 'function'){
html = finalCode = options.codeParse(html);
// 获得初始 code
var rawCode = othis.data(CONST.CDDE_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;
}();
// 记录初始 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 = {
copy: {
className: 'file-b',
title: ['复制代码'],
event: function(el, type){
var text = util.unescape(finalCode);
try {
navigator.clipboard.writeText(text).then(function(){
layer.msg('已复制', {icon: 1});
});
} catch(e) {
var textarea = document.createElement('textarea');
textarea.value = text;
textarea.style.position = 'absolute';
textarea.style.opacity = '0';
document.body.appendChild(textarea);
textarea.select();
try {
document.execCommand('copy');
layer.msg('已复制', {icon: 1});
} catch(err) {
layer.msg('复制失败', {icon: 2});
}
textarea.remove();
$.extend(tools, {
'full': {
className: 'screen-full',
title: ['最大化显示', '还原显示'],
event: function(obj){
var el = obj.elem;
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);
}
typeof options.onCopy === 'function' && options.onCopy(text);
}
},
'window': {
className: 'release',
title: ['在新窗口预览'],
event: function(obj){
util.openWin({
content: finalCode
});
}
}
};
});
// 是否开启预览
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>');
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'];
// 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'];
}
}
// 工具栏事件
elemToolbar.on('click', '>i', function(){
var oi = $(this);
var type = oi.data('type');
tools[type] && typeof tools[type].event === 'function' && tools[type].event(oi, type);
typeof options.toolsEvent === 'function' && options.toolsEvent(oi, type);
});
layui.each(options.tools, function(i, v){
var className = (tools[v] && tools[v].className) || v;
var title = (tools[v] && tools[v].title) || [''];
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);
// 工具栏事件
elemToolbar.on('click', '>i', function(){
var oi = $(this);
var type = oi.data('type');
var parameters = {
elem: oi,
type: type,
options: options, // 当前属性选项
rawCode: rawCode.join(''), // 原始 code
finalCode: util.unescape(finalCode) // 最终 code
};
if(layout[0] === 'preview'){
elemPreviewView.addClass(CONST.ELEM_SHOW);
othis.before(elemPreviewView);
run(elemPreviewView);
} else {
othis.addClass(CONST.ELEM_SHOW).after(elemPreviewView);
}
// 内部 tools event
tools[type] && typeof tools[type].event === 'function' && tools[type].event(parameters);
// 内容项初始化样式
options.codeStyle = [options.style, options.codeStyle].join('');
options.previewStyle = [options.style, options.previewStyle].join('');
// othis.attr('style', options.codeStyle);
elemPreviewView.attr('style', options.previewStyle);
// 外部 tools event
typeof options.toolsEvent === 'function' && options.toolsEvent(parameters);
});
// 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 (options.addTools) {
options.tools = [].concat(options.tools || [], options.addTools);
}
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 listTag = options.ln ? 'ol' : 'ul';
var listElem = $('<'+ listTag +' class="layui-code-'+ listTag +'">');
var className = tool.className || tool.type;
var title = tool.title || [''];
var type = viso ? ( tool.type || className ) : v;
// header
var headerElem = $('<div class="'+ CONST.ELEM_TITLE +'">');
if (!type) return;
// 添加组件 className
othis.addClass('layui-code-view layui-box');
// 自定义风格
if(options.skin){
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');
// 若非内置 tool则合并到 tools 中
if (!tools[type]) {
var obj = {};
obj[type] = tool;
$.extend(tools, obj);
}
})(Math.floor(listElem.find('li').length/100));
// 限制 Code 最大高度
if(options.height){ // 兼容旧版本
listElem.css('max-height', options.height);
}
// Code 内容区域样式
listElem.attr('style', options.codeStyle);
elemToolbar.append(
'<i class="layui-icon layui-icon-'+ className +'" data-type="'+ type +'" title="'+ title[0] +'"></i>'
);
});
// 是否开启代码复制
if(options.copy && !options.preview){
var elemCopy = $(['<span class="'+ CONST.ELEM_COPY +'">',
'<i class="layui-icon layui-icon-file-b" title="复制"></i>',
'</span>'].join(''));
var elemCopyHas = othis.children('.'+ CONST.ELEM_COPY);
var isHeight = listElem[0].style.height || listElem[0].style.maxHeight;
othis.addClass(CONST.ELEM_ITEM).wrap(elemView); // 包裹外层容器
elemTabView.append(elemHeaderView); // 追加标签头
options.tools && elemTabView.append(elemToolbar); // 追加工具栏
othis.before(elemTabView); // 追加标签结构
if(isHeight) elemCopy.addClass(CONST.ELEM_COPY + '-offset'); // 偏移
if(elemCopyHas[0]) elemCopyHas.remove(); // 移除旧的复制元素
othis.append(elemCopy);
// 点击复制
elemCopy.on('click', function(){
tools.copy.event();
});
// 追加预览
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(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 文件
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 device = layui.device();
var MOD_NAME = 'form', ELEM = '.layui-form', THIS = 'layui-this';
var SHOW = 'layui-show', HIDE = 'layui-hide', DISABLED = 'layui-disabled';
var MOD_NAME = 'form';
var ELEM = '.layui-form';
var THIS = 'layui-this';
var SHOW = 'layui-show';
var HIDE = 'layui-hide';
var DISABLED = 'layui-disabled';
var Form = function(){
this.config = {
// 内置的验证规则
verify: {
required: [
/[\S]+/,
'必填项不能为空'
],
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 '只能填写数字';
required: function(value) {
if (!/[\S]+/.test(value)) {
return '必填项不能为空';
}
},
date: [
/^(\d{4})[-\/](\d{1}|0\d{1}|1[0-2])([-\/](\d{1}|0\d{1}|[1-2][0-9]|3[0-1]))*$/,
'日期格式不正确'
],
identity: [
/(^\d{15}$)|(^\d{17}(x|X|\d)$)/,
'请输入正确的身份证号'
]
phone: function(value) {
var EXP = /^1\d{10}$/;
if (value && !EXP.test(value)) {
return '手机号格式不正确';
}
},
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 表示不干预
};
};
@ -894,10 +910,10 @@ layui.define(['lay', 'layer', 'util'], function(exports){
return that;
};
// 主动触发验证 -- elem 即要验证的区域表单选择器 / return true or false
Form.prototype.validate = function(elem){
// 主动触发验证 --- elem 即要验证的区域表单选择器 / return true or false
Form.prototype.validate = function(elem) {
var that = this;
var stop = null; // 验证不通过状态
var intercept; // 拦截标识
var options = that.config; // 获取全局配置项
var verify = options.verify; // 验证规则
var DANGER = 'layui-form-danger'; // 警示样式
@ -905,10 +921,10 @@ layui.define(['lay', 'layer', 'util'], function(exports){
elem = $(elem);
// 节点不存在可视为 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 节点
if (that.validate(elem.find('*[lay-verify]')) === 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 verifyStr = othis.attr('lay-verify') || '';
var vers = verifyStr.split('|');
@ -926,16 +942,16 @@ layui.define(['lay', 'layer', 'util'], function(exports){
othis.removeClass(DANGER); // 移除警示样式
// 遍历元素绑定的验证规则
layui.each(vers, function(_, thisVer){
var isTrue; // 是否命中校验
layui.each(vers, function(_, thisVer) {
var verst; // 校验结果
var errorText = ''; // 错误提示文本
var rule = verify[thisVer]; // 获取校验规则
// 匹配验证规则
if(rule){
isTrue = typeof rule === 'function'
if (rule) {
verst = typeof rule === 'function'
? errorText = rule(value, item)
: !rule[0].test(value);
: !rule[0].test(value); // 兼容早期数组中的正则写法
// 是否属于美化替换后的表单元素
var isForm2Elem = item.tagName.toLowerCase() === 'select' || (
@ -945,20 +961,14 @@ layui.define(['lay', 'layer', 'util'], function(exports){
errorText = errorText || rule[1];
// 获取自定义必填项提示文本
if(thisVer === 'required'){
if (thisVer === 'required') {
errorText = othis.attr('lay-reqtext') || errorText;
}
// 若为必填项或者非空命中校验,则阻止提交,弹出提示
if(isTrue && (
options.verIncludeRequired || (
thisVer === 'required' || (
value && thisVer !== 'required'
)
)
)){
// 若命中校验规则
if (verst) {
// 提示层风格
if(verType === 'tips'){
if (verType === 'tips') {
layer.tips(errorText, function(){
if(typeof othis.attr('lay-ignore') !== 'string'){
if(isForm2Elem){
@ -971,24 +981,24 @@ layui.define(['lay', 'layer', 'util'], function(exports){
layer.alert(errorText, {title: '提示', shadeClose: true});
}
// 若返回的为字符或数字,则自动弹出默认提示框;否则由 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});
}
setTimeout(function(){
setTimeout(function() {
(isForm2Elem ? othis.next().find('input') : item).focus();
}, 7);
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]);
});
};
/*
* 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 对象操作
@ -120,7 +135,7 @@
if (typeof callback === 'function') {
layui.each(rules, function(i, item){
if (callback(item)) return true;
if (callback(item, i)) return true;
});
}
@ -294,6 +309,40 @@
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 元素操作

View File

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

View File

@ -163,7 +163,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
return '';
}()
,'{{# 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-'
,'{{# if(item2.colGroup){ }}'
,'group'
@ -584,7 +584,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
lay.style({
target: that.elem[0],
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
layui.each(data, function(i1, item1){
var tds = [];
var tds = [];
var tds_fixed = [];
var tds_fixed_r = [];
var numbers = i1 + options.limit*(curr - 1) + 1; // 序号
@ -1144,34 +1144,31 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
// td 内容
var td = ['<td data-field="'+ field +'" data-key="'+ key +'" '+ function(){
//追加各种属性
// 追加各种属性
var attr = [];
// 是否开启编辑。若 edit 传入函数,则根据函数的返回结果判断是否开启编辑
(function(edit){
if(edit) attr.push('data-edit="'+ edit +'"'); // 添加单元格编辑属性标识
})(typeof item3.edit === 'function' ? item3.edit(item1) : item3.edit);
if(item3.templet) attr.push('data-content="'+ util.escape(content) +'"'); //自定义模板
if(item3.toolbar) attr.push('data-off="true"'); //行工具列关闭单元格事件
if(item3.templet) attr.push('data-content="'+ util.escape(content) +'"'); // 自定义模板
if(item3.toolbar) attr.push('data-off="true"'); // 行工具列关闭单元格事件
if(item3.event) attr.push('lay-event="'+ item3.event +'"'); //自定义事件
if(item3.minWidth) attr.push('data-minwidth="'+ item3.minWidth +'"'); //单元格最小宽度
if(item3.maxWidth) attr.push('data-maxwidth="'+ item3.maxWidth +'"'); //单元格最大宽度
if(item3.minWidth) attr.push('data-minwidth="'+ item3.minWidth +'"'); // 单元格最小宽度
if(item3.maxWidth) attr.push('data-maxwidth="'+ item3.maxWidth +'"'); // 单元格最大宽度
if(item3.style) attr.push('style="'+ item3.style +'"'); // 自定义单元格样式
return attr.join(' ');
}() +' class="'+ function(){ //追加样式
}() +' class="'+ function(){ // 追加样式
var classNames = [];
if(item3.hide) classNames.push(HIDE); //插入隐藏列样式
if(!item3.field) classNames.push(ELEM_COL_SPECIAL); //插入特殊列样式
if(item3.hide) classNames.push(HIDE); // 插入隐藏列样式
if(!item3.field) classNames.push(ELEM_COL_SPECIAL); // 插入特殊列样式
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
: (key + ' laytable-cell-' + item3.type);
}() +'"'
+ (item3.align ? ' align="'+ item3.align +'"' : '')
+ function(){
var attr = [];
if(item3.style) attr.push('style="'+ item3.style +'"'); //自定义单元格样式
return attr.join(' ');
}() +'>'
+'>'
+ function(){
var tplData = $.extend(true, {
LAY_COL: item3
@ -1179,7 +1176,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
var checkName = table.config.checkName;
var disabledName = table.config.disabledName;
//渲染不同风格的列
// 渲染不同风格的列
switch(item3.type){
case 'checkbox': // 复选
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':
return numbers;
//break;
};
}
//解析工具列模板
if(item3.toolbar){
@ -1313,6 +1310,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
}, 50);
that.haveInit = true;
layer.close(that.tipsIndex);
};
table.cache[that.key] = data; //记录数据
@ -1454,6 +1452,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
var attr = [];
if(item3.minWidth) attr.push('data-minwidth="'+ item3.minWidth +'"'); // 单元格最小宽度
if(item3.maxWidth) attr.push('data-maxwidth="'+ item3.maxWidth +'"'); // 单元格最小宽度
if(item3.style) attr.push('style="'+ item3.style +'"'); // 自定义单元格样式
return attr.join(' ');
}() +' class="'+ function(){ // 追加样式
var classNames = [];
@ -1468,7 +1467,6 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
}() +'"'+ function(){
var attr = [];
if(item3.align) attr.push('align="'+ item3.align +'"'); // 对齐方式
if(item3.style) attr.push('style="'+ item3.style +'"'); // 自定义单元格样式
return attr.join(' ');
}() +'>' + function(){
var totalRow = item3.totalRow || options.totalRow;
@ -1773,7 +1771,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
//获取滚动条宽度
Class.prototype.getScrollWidth = function(elem){
var width = 0;
var width;
if(elem){
width = elem.offsetWidth - elem.clientWidth;
} else {
@ -1793,19 +1791,19 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
Class.prototype.scrollPatch = function(){
var that = this;
var layMainTable = that.layMain.children('table');
var scollWidth = that.layMain.width() - that.layMain.prop('clientWidth'); // 纵向滚动条宽度
var scollHeight = that.layMain.height() - that.layMain.prop('clientHeight'); // 横向滚动条高度
var scrollWidth = that.layMain.width() - that.layMain.prop('clientWidth'); // 纵向滚动条宽度
var scrollHeight = that.layMain.height() - that.layMain.prop('clientHeight'); // 横向滚动条高度
var getScrollWidth = that.getScrollWidth(that.layMain[0]); // 获取主容器滚动条宽度,如果有的话
var outWidth = layMainTable.outerWidth() - that.layMain.width(); // 表格内容器的超出宽度
// 添加补丁
var addPatch = function(elem){
if(scollWidth && scollHeight){
if(scrollWidth && scrollHeight){
elem = elem.eq(0);
if(!elem.find('.layui-table-patch')[0]){
var patchElem = $('<th class="layui-table-patch"><div class="layui-table-cell"></div></th>'); // 补丁元素
patchElem.find('div').css({
width: scollWidth
width: scrollWidth
});
elem.find('tr').append(patchElem);
}
@ -1819,7 +1817,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
// 固定列区域高度
var mainHeight = that.layMain.height();
var fixHeight = mainHeight - scollHeight;
var fixHeight = mainHeight - scrollHeight;
that.layFixed.find(ELEM_BODY).css(
'height',
@ -1834,7 +1832,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
](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);
_DOC.trigger('table.tool.panel.remove');
layer.close(that.tipsIndex);
switch(events){
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.close();
if(layui.device('edg').edg){
printWin.onafterprint = printWin.close;
printWin.print();
@ -2072,6 +2071,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
dict.rule.style.width = setWidth + 'px';
thatTable.setGroupWidth(thisTable.eventMoveElem);
layer.close(that.tipsIndex);
}
}
}).on('mouseup', function(e){
@ -2319,7 +2319,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
].join(',');
if( $(e.target).is(UNROW) || $(e.target).closest(UNROW)[0]){
return;
};
}
setRowEvent.call(this, 'row');
}).on('dblclick', 'tr', function(){ // 双击行
setRowEvent.call(this, 'rowDouble');
@ -2463,44 +2463,75 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
var elemCell = td.children(ELEM_CELL);
var ELEM_CELL_C = 'layui-table-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');
// 设置当前单元格展开宽度
that.cssRules(key, function(item){
var width = item.style.width;
var expandedWidth = col.expandedWidth || (that.elem.width() / 3);
// 展开后的宽度不能小于当前宽度
if(expandedWidth < parseFloat(width)) expandedWidth = parseFloat(width);
elemCellClose.data('cell-width', width);
item.style.width = expandedWidth + 'px';
setTimeout(function(){
that.scrollPatch(); // 滚动条补丁
// 展开风格
if (expandedMode === 'tips') { // TIPS 展开风格
that.tipsIndex = layer.tips([
'<div class="layui-table-tips-main" style="margin-top: -'+ (elemCell.height() + 23) +'px;'+ function(){
if(options.size === 'sm'){
return 'padding: 4px 15px; font-size: 12px;';
}
if(options.size === 'lg'){
return 'padding: 14px 15px;';
}
return '';
}() +'">',
elemCell.html(),
'</div>',
'<i class="layui-icon layui-table-tips-c layui-icon-close"></i>'
].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){
item.style.width = $this.data('cell-width'); // 恢复单元格展开前的宽度
that.resize(); // 滚动条补丁
var width = item.style.width;
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();
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');
// 处理 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(){
var dataTitle = [];
var dataMain = [];
@ -2984,5 +3029,3 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
exports(MOD_NAME, table);
});

View File

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