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

@ -5,11 +5,15 @@ body:
- type: markdown - type: markdown
attributes: attributes:
value: | value: |
**请注意**:此处只接受 Layui 相关技术问题,其他如 layuiAdmin 或 layim 等主题相关问题请勿在此反馈。 **系统提示**:此处只接受 Layui 相关技术问题,其他如 layuiAdmin 或 LayIM 等主题相关问题请勿在此反馈。
<br><br> - type: checkboxes
同时,在反馈问题之前,请确保: attributes:
- 已查看官方使用文档:**https://layui.dev** ,但没有找到相关解决方案。 label: 议题条件
- 已在 **Issues** 中搜索过类似的问题,但没有找到相关解决方案。 options:
- label: 我确认已查看官方使用文档:**https://layui.dev** ,但没有找到相关解决方案。
required: true
- label: 我确认已在 **Issues** 中搜索过类似的问题,但没有找到相关解决方案。
required: true
- type: input - type: input
attributes: attributes:
label: 版本号 label: 版本号
@ -19,7 +23,7 @@ body:
- type: input - type: input
attributes: attributes:
label: 浏览器 label: 浏览器
placeholder: Chrome 115.0.5735.91正式版本 64 位) placeholder: Chrome 116.0.5845.111正式版本 64 位)
validations: validations:
required: true required: true
- type: dropdown - type: dropdown
@ -53,7 +57,8 @@ body:
- type: input - type: input
attributes: attributes:
label: 演示地址 label: 演示地址
placeholder: 若能提供 CodePen、Stackblitz 或自主搭建的页面演示地址,将更有助于解决问题 description: 若能提供 Stackblitz, CodePen 或自主搭建的页面演示地址,将更有助于解决问题
placeholder: URL
- type: checkboxes - type: checkboxes
attributes: attributes:
label: 友好承诺 label: 友好承诺

View File

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

2
dist/css/layui.css vendored

File diff suppressed because one or more lines are too long

2
dist/layui.js vendored

File diff suppressed because one or more lines are too long

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -109,10 +109,10 @@ npm i layui
点击上方 `Preview` 标签可进行效果预览。 点击上方 `Preview` 标签可进行效果预览。
<h2 id="help">其他帮助</h2> <h3 id="help">其他帮助</h3>
- <a href="https://codepen.io/layui/pen/bGxZXrd" target="_blank" rel="nofollow">在线测试</a> - <a href="https://layui.dev/playground/2/">在线测试</a>
- <a href="https://github.com/Sight-wcg/layui-theme-dark" target="_blank">深色主题</a> (社区贡献) - <a href="https://github.com/Sight-wcg/layui-theme-dark" rel="nofollow" target="_blank">深色主题</a> (社区贡献)
## 初识寄语 ## 初识寄语

View File

@ -6,6 +6,8 @@
</textarea> </textarea>
</pre> </pre>
<div class="ws-docs-showcase" style="margin-top: 16px;"></div>
<h3 id="type" lay-toc="{level: 2, hot: true}">弹层类型</h3> <h3 id="type" lay-toc="{level: 2, hot: true}">弹层类型</h3>
<pre class="layui-code" lay-options="{preview: true, codeStyle: 'height: 535px;', text: {preview: '弹层类型'}, layout: ['preview', 'code'], tools: ['full']}"> <pre class="layui-code" lay-options="{preview: true, codeStyle: 'height: 535px;', text: {preview: '弹层类型'}, layout: ['preview', 'code'], tools: ['full']}">

View File

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

View File

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

View File

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

View File

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

View File

@ -73,7 +73,7 @@ layui.use(['table', 'dropdown'], function(){
{type: 'checkbox', fixed: 'left'}, {type: 'checkbox', fixed: 'left'},
{field:'id', fixed: 'left', width:80, title: 'ID', sort: true, totalRowText: '合计:'}, {field:'id', fixed: 'left', width:80, title: 'ID', sort: true, totalRowText: '合计:'},
{field:'username', width:80, title: '用户'}, {field:'username', width:80, title: '用户'},
{field:'email', title:'邮箱 <i class="layui-icon layui-icon-tips layui-font-14" lay-event="email-tips" title="该字段开启了编辑功能" style="margin-left: 5px;"></i>', fieldTitle: '邮箱', hide: 0, width:150, edit: 'text'}, {field:'email', title:'邮箱 <i class="layui-icon layui-icon-tips layui-font-14" lay-event="email-tips" title="该字段开启了编辑功能" style="margin-left: 5px;"></i>', fieldTitle: '邮箱', hide: 0, width:150, expandedMode: 'tips', edit: 'text'},
{field:'sex', width:80, title: '性别', sort: true}, {field:'sex', width:80, title: '性别', sort: true},
{field:'sign', title: '签名', edit: 'textarea', minWidth: 260, expandedWidth: 260, totalRow: '{{!人物:<span class="layui-badge-rim">唐代:{{= d.TOTAL_ROW.era.tang }} </span> <span class="layui-badge-rim">宋代:{{= d.TOTAL_ROW.era.song }}</span> <span class="layui-badge-rim">现代:{{= d.TOTAL_ROW.era.xian }}</span>!}}'}, {field:'sign', title: '签名', edit: 'textarea', minWidth: 260, expandedWidth: 260, totalRow: '{{!人物:<span class="layui-badge-rim">唐代:{{= d.TOTAL_ROW.era.tang }} </span> <span class="layui-badge-rim">宋代:{{= d.TOTAL_ROW.era.song }}</span> <span class="layui-badge-rim">现代:{{= d.TOTAL_ROW.era.xian }}</span>!}}'},
{field:'experience', width: 100, title: '积分', sort: true, totalRow: '{{!{{= d.TOTAL_NUMS }} 😊!}}'}, {field:'experience', width: 100, title: '积分', sort: true, totalRow: '{{!{{= d.TOTAL_NUMS }} 😊!}}'},

View File

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

View File

@ -90,6 +90,16 @@ data: {
</td> </td>
<td>object</td> <td>object</td>
<td>-</td>
</tr>
<tr>
<td>dataType <sup>2.8.17+</sup></td>
<td>
服务端返回的数据类型,如:`text,json,xml` 等
</td>
<td>string</td>
<td>-</td> <td>-</td>
</tr> </tr>
<tr> <tr>

View File

@ -11,6 +11,8 @@ toc: true
以下示例的部分上传接口由第三方网站 `https://httpbin.org` 提供,它可以模拟各类 HTTP 请求。若未配置上传接口的,每次上传都会报「请求上传接口出现异常」的提示,这属于正常现象。 以下示例的部分上传接口由第三方网站 `https://httpbin.org` 提供,它可以模拟各类 HTTP 请求。若未配置上传接口的,每次上传都会报「请求上传接口出现异常」的提示,这属于正常现象。
<div class="ws-docs-showcase"></div>
<div> <div>
{{- d.include("/upload/detail/demo.md") }} {{- d.include("/upload/detail/demo.md") }}
</div> </div>

View File

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

View File

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

View File

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

View File

@ -5,6 +5,7 @@
,"totalRow": { ,"totalRow": {
"checkin": "777" "checkin": "777"
} }
,"data1": []
,"data": [{ ,"data": [{
"id": "10001" "id": "10001"
,"username": "杜甫123" ,"username": "杜甫123"

View File

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

View File

@ -31,6 +31,8 @@
重载测试 重载测试
<i class="layui-icon layui-icon-down layui-font-12"></i> <i class="layui-icon layui-icon-down layui-font-12"></i>
</button> </button>
<button class="layui-btn layui-btn-sm layui-btn-primary" lay-event="multi-row"> 多行 </button>
<button class="layui-btn layui-btn-sm layui-btn-primary" lay-event="default-row"> 单行 </button>
<button class="layui-btn layui-btn-sm" id="moreTest"> <button class="layui-btn layui-btn-sm" id="moreTest">
更多测试 更多测试
<i class="layui-icon layui-icon-down layui-font-12"></i> <i class="layui-icon layui-icon-down layui-font-12"></i>
@ -75,12 +77,12 @@
<table id="test"></table> <table id="test"></table>
<script src="../src/layui.js" src1="https://cdn.staticfile.org/layui/2.7.6/layui.js"></script> <script src="../src/layui.js"></script>
<script> <script>
(function(off){ (function(off){
if(!off) return; if(!off) return;
layui.disuse('table').extend({ layui.disuse('table').extend({
table: '{/}//ww:5018/layui/2.6.13/src/modules/table' table: '{/}https://cdn.staticfile.org/layui/2.7.6/layui.js'
}); });
})(); })();
@ -153,15 +155,17 @@ layui.use(['table', 'dropdown'], function(){
// escape: false, // escape: false,
editTrigger: 'dblclick', editTrigger: 'dblclick',
// cellMaxWidth: 320 // cellMaxWidth: 320
// cellExpandedWidth: 160, // 单元格默认展开后的宽度
// cellExpandedStyle: 'tips', // 单元格默认展开风格
cols: !1 ? test_cols : [[ cols: !1 ? test_cols : [[
{type: 'checkbox', fixed: 'left'}, {type: 'checkbox', fixed: 'left'},
//,{type: 'numbers', fixed: 'left'} // {type: 'numbers', fixed: 'left'},
{field:'id', title:'ID', width:80, fixed: 'left', unresize: true, sort: true, totalRowText: '合计:'}, {field:'id', title:'ID', width:80, fixed: 'left', unresize: true, sort: true, totalRowText: '合计:'},
{field:'username', title:'用户名 <i class="layui-icon layui-icon-username" lay-event="username"></i>', width:120, edit: function(d){ {field:'username', expandedStyle: 'tips', title:'用户名 <i class="layui-icon layui-icon-username" lay-event="username"></i>', width:120, edit: function(d){
return !d.LAY_DISABLED; return !d.LAY_DISABLED;
}, templet: '#usernameTpl'}, }, templet: '#usernameTpl'},
{field:'xxx', title:'测试', edit: 'text'}, {field:'xxx', title:'测试', edit: 'text'},
{field:'email', minWidth: 160, maxWidth: 320, title:'邮箱 <i class="layui-icon layui-icon-email" lay-event="email"></i>', fieldTitle: '邮箱', hide: 0, edit: 'text', templet: function(d){ {field:'email', minWidth: 160, maxWidth: 320, title:'邮箱 <i class="layui-icon layui-icon-email" lay-event="email"></i>', fieldTitle: '邮箱', hide: 0, edit: 'text', style: 'background-color: #fafafa; color: red;', templet: function(d){
return '<em>'+ layui.util.escape(d.email) +'</em>' return '<em>'+ layui.util.escape(d.email) +'</em>'
}}, }},
{field:'sex', title:'性别', width:80, edit: 'text', sort: true, escape: false}, {field:'sex', title:'性别', width:80, edit: 'text', sort: true, escape: false},
@ -171,7 +175,7 @@ layui.use(['table', 'dropdown'], function(){
var td = obj.td(this.field); //获取当前 td var td = obj.td(this.field); //获取当前 td
return td.find('select').val(); return td.find('select').val();
}}, }},
{field:'sign', title:'签名', minWidth: 200, expandedWidth: 350, style:'color: #5FB878', edit: 'textarea'}, {field:'sign', title:'签名', minWidth: 200, style:'color: #5FB878', edit: 'textarea'},
{field: 'experience', title: '积分', width: 100, sort: true, align:'center', totalRow: !1 ? true : '{{= d.TOTAL_NUMS }} 分 😊', templet: '<div><a href="" class="layui-table-link">{{= d[d.LAY_COL.field] }}</a></div>'}, {field: 'experience', title: '积分', width: 100, sort: true, align:'center', totalRow: !1 ? true : '{{= d.TOTAL_NUMS }} 分 😊', templet: '<div><a href="" class="layui-table-link">{{= d[d.LAY_COL.field] }}</a></div>'},
{field:'ip', title:'IP', width: 120, align: 'right'}, {field:'ip', title:'IP', width: 120, align: 'right'},
{field:'checkin', title:'打卡', width: 100, sort: true, totalRow: '{{= d.TOTAL_ROW.checkin }} 次'}, {field:'checkin', title:'打卡', width: 100, sort: true, totalRow: '{{= d.TOTAL_ROW.checkin }} 次'},
@ -336,7 +340,6 @@ layui.use(['table', 'dropdown'], function(){
} }
}); });
// 更多测试 // 更多测试
dropdown.render({ dropdown.render({
elem: '#moreTest', // 可绑定在任意元素中,此处以上述按钮为例 elem: '#moreTest', // 可绑定在任意元素中,此处以上述按钮为例
@ -439,6 +442,19 @@ layui.use(['table', 'dropdown'], function(){
case 'isAll': case 'isAll':
layer.msg(checkStatus.isAll ? '全选': '未全选') layer.msg(checkStatus.isAll ? '全选': '未全选')
break; break;
case 'multi-row':
table.reload('test', {
// 设置行样式,此处以设置多行高度为例。若为单行,则没必要设置改参数 - 注v2.7.0 新增
lineStyle: 'height: 95px;'
});
layer.msg('即通过设置 lineStyle 参数可开启多行');
break;
case 'default-row':
table.reload('test', {
lineStyle: null // 恢复单行
});
layer.msg('已设为单行');
break;
case 'LAYTABLE_TIPS': case 'LAYTABLE_TIPS':
layer.alert('Table for layui-v'+ layui.v); layer.alert('Table for layui-v'+ layui.v);
break; break;
@ -454,12 +470,7 @@ layui.use(['table', 'dropdown'], function(){
table.on('tool(test)', function(obj){ // 双击 toolDouble table.on('tool(test)', function(obj){ // 双击 toolDouble
var data = obj.data; var data = obj.data;
// console.log(obj) // console.log(obj)
if(obj.event === 'del'){ if (obj.event === 'edit') {
layer.confirm('真的删除行么', function(index){
obj.del();
layer.close(index);
});
} else if(obj.event === 'edit'){
layer.prompt({ layer.prompt({
formType: 2 formType: 2
,value: data.email ,value: data.email
@ -477,11 +488,14 @@ layui.use(['table', 'dropdown'], function(){
*/ */
layer.close(index); layer.close(index);
}); });
} else if (obj.event === 'del') {
layer.confirm('真的删除行么', function(index){
obj.del();
layer.close(index);
});
} }
}); });
// 触发表格复选框选择 // 触发表格复选框选择
table.on('checkbox(test)', function(obj){ table.on('checkbox(test)', function(obj){
console.log(obj) console.log(obj)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -11,22 +11,28 @@ layui.define(['lay', 'util', 'element', 'form'], function(exports){
var element = layui.element; var element = layui.element;
var form = layui.form; var form = layui.form;
var layer = layui.layer; var layer = layui.layer;
var hint = layui.hint();
// 常量 // 常量
var CONST = { var CONST = {
ELEM_VIEW: 'layui-code-view', ELEM_VIEW: 'layui-code-view',
ELEM_COPY: 'layui-code-copy',
ELEM_TAB: 'layui-tab', ELEM_TAB: 'layui-tab',
ELEM_TITLE: 'layui-code-title', ELEM_HEADER: 'layui-code-header',
ELEM_FULL: 'layui-code-full', ELEM_FULL: 'layui-code-full',
ELEM_PREVIEW: 'layui-code-preview', ELEM_PREVIEW: 'layui-code-preview',
ELEM_ITEM: 'layui-code-item', ELEM_ITEM: 'layui-code-item',
ELEM_SHOW: 'layui-show' ELEM_SHOW: 'layui-show',
ELEM_LINE: 'layui-code-line',
ELEM_LINE_NUM: 'layui-code-line-number',
ELEM_LN_MODE: 'layui-code-ln-mode',
CDDE_DATA_CODE: 'LayuiCodeDataCode',
CDDE_DATA_CLASS: 'LayuiCodeDataClass',
LINE_RAW_WIDTH: 45, // 行号初始宽度,需与 css 保持一致
}; };
// 默认参数项 // 默认参数项
var config = { var config = {
elem: '.layui-code', // 元素选择器 elem: '', // 元素选择器
about: '', // 代码栏右上角信息 about: '', // 代码栏右上角信息
ln: true, // 代码区域是否显示行号 ln: true, // 代码区域是否显示行号
header: false, // 是否显示代码栏头部区域 header: false, // 是否显示代码栏头部区域
@ -35,28 +41,64 @@ layui.define(['lay', 'util', 'element', 'form'], function(exports){
// 默认文本 // 默认文本
text: { text: {
code: util.escape('</>'), code: util.escape('</>'),
preview: 'Preview' preview: 'Preview',
} },
wordWrap: true, // 是否自动换行
lang: 'text', // 指定语言类型
highlighter: false, // 是否开启语法高亮,'hljs','prism','shiki'
langMarker: false, // 代码区域是否显示语言类型标记
}; };
// 初始索引
var codeIndex = layui.code ? (layui.code.index + 10000) : 0;
// 去除尾部空格
var trimEnd = function(str){
return String(str).replace(/\s+$/, '');
}
// 保留首行缩进
var trim = function(str){ var trim = function(str){
return $.trim(str).replace(/^\n|\n$/, ''); return trimEnd(str).replace(/^\n|\n$/, '');
}; };
// export api // export api
exports('code', function(options){ exports('code', function(options, mode){
var opts = options = $.extend(true, {}, config, options); options = $.extend(true, {}, config, options);
// 返回对象
var ret = {
config: options,
reload: function(opts) { // 重载
layui.code(this.updateOptions(opts));
},
updateOptions: function(opts) { // 更新属性(选项)
opts = opts || {};
delete opts.elem;
return $.extend(true, options, opts);
},
reloadCode: function(opts) { // 仅重载 code
layui.code(this.updateOptions(opts), 'reloadCode');
}
};
// 若 elem 非唯一
var elem = $(options.elem);
if(elem.length > 1){
// 是否正向渲染
layui.each(options.obverse ? elem : elem.get().reverse(), function(){
layui.code($.extend({}, options, {
elem: this
}), mode);
});
return ret;
}
// 目标元素是否存在 // 目标元素是否存在
options.elem = $(options.elem); var othis = options.elem = $(options.elem);
if(!options.elem[0]) return; if(!othis[0]) return ret;
// 从内至外渲染
layui.each(options.elem.get().reverse(), function(index, item){
var othis = $(item);
// 合并属性上的参数,并兼容旧版本属性写法 lay-* // 合并属性上的参数,并兼容旧版本属性写法 lay-*
var options = $.extend(true, {}, opts, lay.options(item), function(obj){ $.extend(true, options, lay.options(othis[0]), function(obj){
var attrs = ['title', 'height', 'encode', 'skin', 'about']; var attrs = ['title', 'height', 'encode', 'skin', 'about'];
layui.each(attrs, function(i, attr){ layui.each(attrs, function(i, attr){
var value = othis.attr('lay-'+ attr); var value = othis.attr('lay-'+ attr);
@ -67,11 +109,15 @@ layui.define(['lay', 'util', 'element', 'form'], function(exports){
return obj; return obj;
}({})); }({}));
// codeRender 需要关闭编码
// 未使用 codeRender 时若开启了预览,则强制开启编码
options.encode = (options.encode || options.preview) && !options.codeRender;
// 最终显示的代码 // 最终显示的代码
var finalCode; var finalCode;
// 获得初始代码 // 获得初始 code
var codes = othis.data('code') || function(){ var rawCode = othis.data(CONST.CDDE_DATA_CODE) || function(){
var arr = []; var arr = [];
var textarea = othis.children('textarea'); var textarea = othis.children('textarea');
@ -88,10 +134,69 @@ layui.define(['lay', 'util', 'element', 'form'], function(exports){
return arr; return arr;
}(); }();
othis.data('code', codes); // 记录初始 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 // code
var html = finalCode = codes.join(''); var html = finalCode = rawCode.join('');
// 外部重新解析 code // 外部重新解析 code
if(typeof options.codeParse === 'function'){ if(typeof options.codeParse === 'function'){
@ -103,32 +208,39 @@ layui.define(['lay', 'util', 'element', 'form'], function(exports){
copy: { copy: {
className: 'file-b', className: 'file-b',
title: ['复制代码'], title: ['复制代码'],
event: function(el, type){ event: function(obj){
var text = util.unescape(finalCode); var code = util.unescape(finalCode);
try {
navigator.clipboard.writeText(text).then(function(){ // 写入剪切板
lay.clipboard.writeText({
text: code,
done: function() {
layer.msg('已复制', {icon: 1}); layer.msg('已复制', {icon: 1});
}); },
} catch(e) { error: function() {
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}); layer.msg('复制失败', {icon: 2});
} }
textarea.remove(); });
}
typeof options.onCopy === 'function' && options.onCopy(text); 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){ if(options.preview){
var FILTER_VALUE = 'LAY-CODE-DF-'+ index; var FILTER_VALUE = 'LAY-CODE-DF-'+ index;
@ -145,17 +257,12 @@ layui.define(['lay', 'util', 'element', 'form'], function(exports){
'layui-border' 'layui-border'
].join(' ') +'">'); ].join(' ') +'">');
var elemToolbar = $('<div class="layui-code-tools"></div>'); 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); if(options.id) elemView.attr('id', options.id);
elemView.addClass(options.className); elemView.addClass(options.className);
elemTabView.attr('lay-filter', FILTER_VALUE); elemTabView.attr('lay-filter', FILTER_VALUE);
// 若开启预览,则强制对 code 进行编码
options.encode = true;
// 标签头 // 标签头
layui.each(layout, function(i, v){ layui.each(layout, function(i, v){
var li = $('<li lay-id="'+ v +'">'); var li = $('<li lay-id="'+ v +'">');
@ -169,7 +276,8 @@ layui.define(['lay', 'util', 'element', 'form'], function(exports){
'full': { 'full': {
className: 'screen-full', className: 'screen-full',
title: ['最大化显示', '还原显示'], title: ['最大化显示', '还原显示'],
event: function(el, type){ event: function(obj){
var el = obj.elem;
var elemView = el.closest('.'+ CONST.ELEM_PREVIEW); var elemView = el.closest('.'+ CONST.ELEM_PREVIEW);
var classNameFull = 'layui-icon-'+ this.className; var classNameFull = 'layui-icon-'+ this.className;
var classNameRestore = 'layui-icon-screen-restore'; var classNameRestore = 'layui-icon-screen-restore';
@ -193,7 +301,7 @@ layui.define(['lay', 'util', 'element', 'form'], function(exports){
'window': { 'window': {
className: 'release', className: 'release',
title: ['在新窗口预览'], title: ['在新窗口预览'],
event: function(el, type){ event: function(obj){
util.openWin({ util.openWin({
content: finalCode content: finalCode
}); });
@ -217,26 +325,58 @@ layui.define(['lay', 'util', 'element', 'form'], function(exports){
elemToolbar.on('click', '>i', function(){ elemToolbar.on('click', '>i', function(){
var oi = $(this); var oi = $(this);
var type = oi.data('type'); var type = oi.data('type');
tools[type] && typeof tools[type].event === 'function' && tools[type].event(oi, type); var parameters = {
typeof options.toolsEvent === 'function' && options.toolsEvent(oi, type); elem: oi,
type: type,
options: options, // 当前属性选项
rawCode: rawCode.join(''), // 原始 code
finalCode: util.unescape(finalCode) // 最终 code
};
// 内部 tools event
tools[type] && typeof tools[type].event === 'function' && tools[type].event(parameters);
// 外部 tools event
typeof options.toolsEvent === 'function' && options.toolsEvent(parameters);
}); });
// 增加工具栏
if (options.addTools) {
options.tools = [].concat(options.tools || [], options.addTools);
}
// 渲染工具栏
layui.each(options.tools, function(i, v){ layui.each(options.tools, function(i, v){
var className = (tools[v] && tools[v].className) || v; var viso = typeof v === 'object'; // 若为 object 值,则可自定义更多属性
var title = (tools[v] && tools[v].title) || ['']; var tool = viso ? v : (
tools[v] || {
className: v,
title: [v]
}
);
var className = tool.className || tool.type;
var title = tool.title || [''];
var type = viso ? ( tool.type || className ) : v;
if (!type) return;
// 若非内置 tool则合并到 tools 中
if (!tools[type]) {
var obj = {};
obj[type] = tool;
$.extend(tools, obj);
}
elemToolbar.append( elemToolbar.append(
'<i class="layui-icon layui-icon-'+ className +'" data-type="'+ v +'" title="'+ title[0] +'"></i>' '<i class="layui-icon layui-icon-'+ className +'" data-type="'+ type +'" title="'+ title[0] +'"></i>'
); );
}); });
// 移除旧结构 othis.addClass(CONST.ELEM_ITEM).wrap(elemView); // 包裹外层容器
if(elemTabHas[0]) elemTabHas.remove(); // 移除 tab
if(elemPreviewViewHas[0]) elemPreviewViewHas.remove(); // 移除预览区域
if(elemViewHas[0]) othis.unwrap(); // 移除外层容器
elemTabView.append(elemHeaderView); // 追加标签头 elemTabView.append(elemHeaderView); // 追加标签头
options.tools && elemTabView.append(elemToolbar); // 追加工具栏 options.tools && elemTabView.append(elemToolbar); // 追加工具栏
othis.wrap(elemView).addClass(CONST.ELEM_ITEM).before(elemTabView); // 追加标签结构 othis.before(elemTabView); // 追加标签结构
// 追加预览 // 追加预览
if(isIframePreview){ if(isIframePreview){
@ -249,7 +389,7 @@ layui.define(['lay', 'util', 'element', 'form'], function(exports){
if(isIframePreview && iframe){ if(isIframePreview && iframe){
iframe.srcdoc = finalCode; iframe.srcdoc = finalCode;
} else { } else {
thisItemBody.html(codes.join('')); thisItemBody.html(rawCode.join(''));
} }
// 回调的返回参数 // 回调的返回参数
var params = { var params = {
@ -259,6 +399,7 @@ layui.define(['lay', 'util', 'element', 'form'], function(exports){
element.render(); element.render();
} }
}; };
// 当前实例预览完毕后的回调 // 当前实例预览完毕后的回调
setTimeout(function(){ setTimeout(function(){
typeof options.done === 'function' && options.done(params); typeof options.done === 'function' && options.done(params);
@ -274,9 +415,7 @@ layui.define(['lay', 'util', 'element', 'form'], function(exports){
} }
// 内容项初始化样式 // 内容项初始化样式
options.codeStyle = [options.style, options.codeStyle].join('');
options.previewStyle = [options.style, options.previewStyle].join(''); options.previewStyle = [options.style, options.previewStyle].join('');
// othis.attr('style', options.codeStyle);
elemPreviewView.attr('style', options.previewStyle); elemPreviewView.attr('style', options.previewStyle);
// tab change // tab change
@ -292,88 +431,172 @@ layui.define(['lay', 'util', 'element', 'form'], function(exports){
if($this.attr('lay-id') === 'preview'){ if($this.attr('lay-id') === 'preview'){
run(thisItemBody); run(thisItemBody);
} }
setCodeLayout();
}); });
} }
// 有序或无序列表 // 创建 code 容器
var listTag = options.ln ? 'ol' : 'ul'; var codeElem = $('<code class="layui-code-wrap"></code>'); // 此处的闭合标签是为了兼容 IE8
var listElem = $('<'+ listTag +' class="layui-code-'+ listTag +'">');
// header // 添加主容器 className
var headerElem = $('<div class="'+ CONST.ELEM_TITLE +'">'); othis.addClass(function(arr) {
if (!options.wordWrap) arr.push('layui-code-nowrap');
return arr.join(' ')
}(['layui-code-view layui-border-box']));
// 添加组件 className // code 主题风格
othis.addClass('layui-code-view layui-box'); var theme = options.theme || options.skin;
if (theme) {
// 自定义风格 othis.removeClass('layui-code-theme-dark layui-code-theme-light');
if(options.skin){ othis.addClass('layui-code-theme-'+ theme);
if(options.skin === 'notepad') options.skin = 'dark';
othis.removeClass('layui-code-dark layui-code-light');
othis.addClass('layui-code-'+ options.skin);
} }
// 添加高亮必要的 className
if (options.highlighter) {
othis.addClass([
options.highlighter,
'language-' + options.lang,
'layui-code-hl'
].join(' '));
}
// 转义 HTML 标签 // 转义 HTML 标签
if(options.encode) html = util.escape(html); // 编码 if(options.encode) html = util.escape(html); // 编码
html = html.replace(/[\r\t\n]+/g, '</li><li>'); // 转义换行符
// 生成列表 var createCodeRst = createCode(html);
othis.html(listElem.html('<li>' + html + '</li>')); var lines = createCodeRst.lines;
// 创建 header // 插入 code
if(options.header && !othis.children('.'+ CONST.ELEM_TITLE)[0]){ othis.html(codeElem.html(createCodeRst.html));
headerElem.html((options.title || options.text.code) + (
options.about // 插入行号边栏
? '<div class="layui-code-about">' + options.about + '</div>' 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); 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){ if(options.elem.length === index + 1){
typeof options.allDone === 'function' && options.allDone(); typeof options.allDone === 'function' && options.allDone();
} }
// 按行数适配左边距 return ret;
(function(autoIncNums){
if(autoIncNums > 0){
listElem.css('margin-left', autoIncNums + 'px');
}
})(Math.floor(listElem.find('li').length/100));
// 限制 Code 最大高度
if(options.height){ // 兼容旧版本
listElem.css('max-height', options.height);
}
// Code 内容区域样式
listElem.attr('style', options.codeStyle);
// 是否开启代码复制
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;
if(isHeight) elemCopy.addClass(CONST.ELEM_COPY + '-offset'); // 偏移
if(elemCopyHas[0]) elemCopyHas.remove(); // 移除旧的复制元素
othis.append(elemCopy);
// 点击复制
elemCopy.on('click', function(){
tools.copy.event();
});
}
});
}); });
}); });
// 若为源码版,则自动加载该组件依赖的 css 文件 // 若为源码版,则自动加载该组件依赖的 css 文件
if(!layui['layui.all']){ if(!layui['layui.all']){
layui.addcss('modules/code.css?v=3', 'skincodecss'); layui.addcss('modules/code.css?v=6', 'skincodecss');
} }

View File

@ -11,42 +11,58 @@ layui.define(['lay', 'layer', 'util'], function(exports){
var hint = layui.hint(); var hint = layui.hint();
var device = layui.device(); var device = layui.device();
var MOD_NAME = 'form', ELEM = '.layui-form', THIS = 'layui-this'; var MOD_NAME = 'form';
var SHOW = 'layui-show', HIDE = 'layui-hide', DISABLED = 'layui-disabled'; var ELEM = '.layui-form';
var THIS = 'layui-this';
var SHOW = 'layui-show';
var HIDE = 'layui-hide';
var DISABLED = 'layui-disabled';
var Form = function(){ var Form = function(){
this.config = { this.config = {
// 内置的验证规则 // 内置的验证规则
verify: { verify: {
required: [ required: function(value) {
/[\S]+/, if (!/[\S]+/.test(value)) {
'必填项不能为空' return '必填项不能为空';
], }
phone: [ },
/^1\d{10}$/, phone: function(value) {
'请输入正确的手机号' var EXP = /^1\d{10}$/;
], if (value && !EXP.test(value)) {
email: [ return '手机号格式不正确';
/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/, }
'邮箱格式不正确' },
], email: function(value) {
url: [ var EXP = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
/^(#|(http(s?)):\/\/|\/\/)[^\s]+\.[^\s]+$/, if (value && !EXP.test(value)) {
'链接格式不正确' return '邮箱格式不正确';
], }
},
url: function(value) {
var EXP = /^(#|(http(s?)):\/\/|\/\/)[^\s]+\.[^\s]+$/;
if (value && !EXP.test(value)) {
return '链接格式不正确';
}
},
number: function(value){ number: function(value){
if(isNaN(value)) return '只能填写数字'; if (value && isNaN(value)) {
return '只能填写数字';
}
}, },
date: [ date: function(value){
/^(\d{4})[-\/](\d{1}|0\d{1}|1[0-2])([-\/](\d{1}|0\d{1}|[1-2][0-9]|3[0-1]))*$/, var EXP = /^(\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: [ }
/(^\d{15}$)|(^\d{17}(x|X|\d)$)/, },
'请输入正确的身份证号' identity: function(value) {
] var EXP = /(^\d{15}$)|(^\d{17}(x|X|\d)$)/;
if (value && !EXP.test(value)) {
return '身份证号格式不正确';
}
}
}, },
verIncludeRequired: false, // 验证规则是否包含必填 --- 为兼容旧版的验证机制
autocomplete: null // 全局 autocomplete 状态。 null 表示不干预 autocomplete: null // 全局 autocomplete 状态。 null 表示不干预
}; };
}; };
@ -894,10 +910,10 @@ layui.define(['lay', 'layer', 'util'], function(exports){
return that; return that;
}; };
// 主动触发验证 -- elem 即要验证的区域表单选择器 / return true or false // 主动触发验证 --- elem 即要验证的区域表单选择器 / return true or false
Form.prototype.validate = function(elem) { Form.prototype.validate = function(elem) {
var that = this; var that = this;
var stop = null; // 验证不通过状态 var intercept; // 拦截标识
var options = that.config; // 获取全局配置项 var options = that.config; // 获取全局配置项
var verify = options.verify; // 验证规则 var verify = options.verify; // 验证规则
var DANGER = 'layui-form-danger'; // 警示样式 var DANGER = 'layui-form-danger'; // 警示样式
@ -927,15 +943,15 @@ layui.define(['lay', 'layer', 'util'], function(exports){
// 遍历元素绑定的验证规则 // 遍历元素绑定的验证规则
layui.each(vers, function(_, thisVer) { layui.each(vers, function(_, thisVer) {
var isTrue; // 是否命中校验 var verst; // 校验结果
var errorText = ''; // 错误提示文本 var errorText = ''; // 错误提示文本
var rule = verify[thisVer]; // 获取校验规则 var rule = verify[thisVer]; // 获取校验规则
// 匹配验证规则 // 匹配验证规则
if (rule) { if (rule) {
isTrue = typeof rule === 'function' verst = typeof rule === 'function'
? errorText = rule(value, item) ? errorText = rule(value, item)
: !rule[0].test(value); : !rule[0].test(value); // 兼容早期数组中的正则写法
// 是否属于美化替换后的表单元素 // 是否属于美化替换后的表单元素
var isForm2Elem = item.tagName.toLowerCase() === 'select' || ( var isForm2Elem = item.tagName.toLowerCase() === 'select' || (
@ -949,14 +965,8 @@ layui.define(['lay', 'layer', 'util'], function(exports){
errorText = othis.attr('lay-reqtext') || errorText; errorText = othis.attr('lay-reqtext') || errorText;
} }
// 若为必填项或者非空命中校验,则阻止提交,弹出提示 // 若命中校验规则
if(isTrue && ( if (verst) {
options.verIncludeRequired || (
thisVer === 'required' || (
value && thisVer !== 'required'
)
)
)){
// 提示层风格 // 提示层风格
if (verType === 'tips') { if (verType === 'tips') {
layer.tips(errorText, function(){ layer.tips(errorText, function(){
@ -980,15 +990,15 @@ layui.define(['lay', 'layer', 'util'], function(exports){
}, 7); }, 7);
othis.addClass(DANGER); othis.addClass(DANGER);
return stop = true; return intercept = true;
} }
} }
}); });
if(stop) return stop; if (intercept) return intercept;
}); });
return !stop; return !intercept;
}; };
// 提交表单并校验 // 提交表单并校验

View File

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

View File

@ -1041,6 +1041,7 @@
that.hint('value ' + lang.invalidDate + lang.formatError[1]); that.hint('value ' + lang.invalidDate + lang.formatError[1]);
} }
// 初始赋值 startDate,endState
that.startDate = that.startDate || value && lay.extend({}, options.dateTime); // 有默认值才初始化startDate that.startDate = that.startDate || value && lay.extend({}, options.dateTime); // 有默认值才初始化startDate
that.autoCalendarModel.auto && that.autoCalendarModel(); that.autoCalendarModel.auto && that.autoCalendarModel();
that.endState = !options.range || !that.rangeLinked || !!(that.startDate && that.endDate); // 初始化选中范围状态 that.endState = !options.range || !that.rangeLinked || !!(that.startDate && that.endDate); // 初始化选中范围状态
@ -1586,16 +1587,17 @@
// 转义为规定格式的日期字符 // 转义为规定格式的日期字符
Class.prototype.parse = function(state, date) { Class.prototype.parse = function(state, date) {
var that = this var that = this;
,options = that.config var options = that.config;
,dateTime = date || (state == 'end' var startDate = (that.rangeLinked ? that.startDate : options.dateTime)
? lay.extend({}, that.endDate, that.endTime) var dateTime = date || (
: ( state == 'end' ? lay.extend({}, that.endDate, that.endTime) : (
options.range options.range
? lay.extend({}, that.rangeLinked ? that.startDate : options.dateTime, that.startTime) ? lay.extend({}, startDate || options.dateTime, that.startTime)
: options.dateTime) : options.dateTime
) )
,format = laydate.parse(dateTime, that.format, 1); );
var format = laydate.parse(dateTime, that.format, 1);
// 返回日期范围字符 // 返回日期范围字符
if (options.range && state === undefined) { if (options.range && state === undefined) {
@ -1758,10 +1760,12 @@
// 执行 done/change 回调 // 执行 done/change 回调
Class.prototype.done = function(param, type){ Class.prototype.done = function(param, type){
var that = this var that = this;
,options = that.config var options = that.config;
,start = lay.extend({}, lay.extend(options.dateTime, that.startTime)) var start = lay.extend({},
,end = lay.extend({}, lay.extend(that.endDate, that.endTime)) lay.extend(that.rangeLinked ? that.startDate : options.dateTime, that.startTime)
);
var end = lay.extend({}, lay.extend(that.endDate, that.endTime));
lay.each([start, end], function(i, item){ lay.each([start, end], function(i, item){
if(!('month' in item)) return; if(!('month' in item)) return;

View File

@ -163,7 +163,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
return ''; return '';
}() }()
,'{{# var isSort = !(item2.colGroup) && item2.sort; }}' ,'{{# var isSort = !(item2.colGroup) && item2.sort; }}'
,'<th data-field="{{= item2.field||i2 }}" data-key="{{=d.index}}-{{=i1}}-{{=i2}}" {{# if( item2.parentKey){ }}data-parentkey="{{= item2.parentKey }}"{{# } }} {{# if(item2.minWidth){ }}data-minwidth="{{=item2.minWidth}}"{{# } }} {{# if(item2.maxWidth){ }}data-maxwidth="{{=item2.maxWidth}}"{{# } }} '+ rowCols +' {{# if(item2.unresize || item2.colGroup){ }}data-unresize="true"{{# } }} class="{{# if(item2.hide){ }}layui-hide{{# } }}{{# if(isSort){ }} layui-unselect{{# } }}{{# if(!item2.field){ }} layui-table-col-special{{# } }}"{{# if(item2.title){ }} title="{{ layui.$(\'<div>\' + item2.title + \'</div>\').text() }}"{{# } }}>' ,'<th data-field="{{= item2.field||i2 }}" data-key="{{=d.index}}-{{=i1}}-{{=i2}}" {{# if( item2.parentKey){ }}data-parentkey="{{= item2.parentKey }}"{{# } }} {{# if(item2.minWidth){ }}data-minwidth="{{=item2.minWidth}}"{{# } }} {{# if(item2.maxWidth){ }}data-maxwidth="{{=item2.maxWidth}}"{{# } }} {{# if(item2.style){ }}style="{{=item2.style}}"{{# } }} '+ rowCols +' {{# if(item2.unresize || item2.colGroup){ }}data-unresize="true"{{# } }} class="{{# if(item2.hide){ }}layui-hide{{# } }}{{# if(isSort){ }} layui-unselect{{# } }}{{# if(!item2.field){ }} layui-table-col-special{{# } }}"{{# if(item2.title){ }} title="{{ layui.$(\'<div>\' + item2.title + \'</div>\').text() }}"{{# } }}>'
,'<div class="layui-table-cell laytable-cell-' ,'<div class="layui-table-cell laytable-cell-'
,'{{# if(item2.colGroup){ }}' ,'{{# if(item2.colGroup){ }}'
,'group' ,'group'
@ -584,7 +584,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
lay.style({ lay.style({
target: that.elem[0], target: that.elem[0],
text: text.join(''), text: text.join(''),
id: 'DF-'+ index id: 'DF-table-'+ index
}); });
}; };
@ -1155,6 +1155,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
if(item3.event) attr.push('lay-event="'+ item3.event +'"'); //自定义事件 if(item3.event) attr.push('lay-event="'+ item3.event +'"'); //自定义事件
if(item3.minWidth) attr.push('data-minwidth="'+ item3.minWidth +'"'); // 单元格最小宽度 if(item3.minWidth) attr.push('data-minwidth="'+ item3.minWidth +'"'); // 单元格最小宽度
if(item3.maxWidth) attr.push('data-maxwidth="'+ item3.maxWidth +'"'); // 单元格最大宽度 if(item3.maxWidth) attr.push('data-maxwidth="'+ item3.maxWidth +'"'); // 单元格最大宽度
if(item3.style) attr.push('style="'+ item3.style +'"'); // 自定义单元格样式
return attr.join(' '); return attr.join(' ');
}() +' class="'+ function(){ // 追加样式 }() +' class="'+ function(){ // 追加样式
var classNames = []; var classNames = [];
@ -1167,11 +1168,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
: (key + ' laytable-cell-' + item3.type); : (key + ' laytable-cell-' + item3.type);
}() +'"' }() +'"'
+ (item3.align ? ' align="'+ item3.align +'"' : '') + (item3.align ? ' align="'+ item3.align +'"' : '')
+ function(){ +'>'
var attr = [];
if(item3.style) attr.push('style="'+ item3.style +'"'); //自定义单元格样式
return attr.join(' ');
}() +'>'
+ function(){ + function(){
var tplData = $.extend(true, { var tplData = $.extend(true, {
LAY_COL: item3 LAY_COL: item3
@ -1211,7 +1208,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
case 'numbers': case 'numbers':
return numbers; return numbers;
//break; //break;
}; }
//解析工具列模板 //解析工具列模板
if(item3.toolbar){ if(item3.toolbar){
@ -1313,6 +1310,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
}, 50); }, 50);
that.haveInit = true; that.haveInit = true;
layer.close(that.tipsIndex);
}; };
table.cache[that.key] = data; //记录数据 table.cache[that.key] = data; //记录数据
@ -1454,6 +1452,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
var attr = []; var attr = [];
if(item3.minWidth) attr.push('data-minwidth="'+ item3.minWidth +'"'); // 单元格最小宽度 if(item3.minWidth) attr.push('data-minwidth="'+ item3.minWidth +'"'); // 单元格最小宽度
if(item3.maxWidth) attr.push('data-maxwidth="'+ item3.maxWidth +'"'); // 单元格最小宽度 if(item3.maxWidth) attr.push('data-maxwidth="'+ item3.maxWidth +'"'); // 单元格最小宽度
if(item3.style) attr.push('style="'+ item3.style +'"'); // 自定义单元格样式
return attr.join(' '); return attr.join(' ');
}() +' class="'+ function(){ // 追加样式 }() +' class="'+ function(){ // 追加样式
var classNames = []; var classNames = [];
@ -1468,7 +1467,6 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
}() +'"'+ function(){ }() +'"'+ function(){
var attr = []; var attr = [];
if(item3.align) attr.push('align="'+ item3.align +'"'); // 对齐方式 if(item3.align) attr.push('align="'+ item3.align +'"'); // 对齐方式
if(item3.style) attr.push('style="'+ item3.style +'"'); // 自定义单元格样式
return attr.join(' '); return attr.join(' ');
}() +'>' + function(){ }() +'>' + function(){
var totalRow = item3.totalRow || options.totalRow; var totalRow = item3.totalRow || options.totalRow;
@ -1773,7 +1771,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
//获取滚动条宽度 //获取滚动条宽度
Class.prototype.getScrollWidth = function(elem){ Class.prototype.getScrollWidth = function(elem){
var width = 0; var width;
if(elem){ if(elem){
width = elem.offsetWidth - elem.clientWidth; width = elem.offsetWidth - elem.clientWidth;
} else { } else {
@ -1793,19 +1791,19 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
Class.prototype.scrollPatch = function(){ Class.prototype.scrollPatch = function(){
var that = this; var that = this;
var layMainTable = that.layMain.children('table'); var layMainTable = that.layMain.children('table');
var scollWidth = that.layMain.width() - that.layMain.prop('clientWidth'); // 纵向滚动条宽度 var scrollWidth = that.layMain.width() - that.layMain.prop('clientWidth'); // 纵向滚动条宽度
var scollHeight = that.layMain.height() - that.layMain.prop('clientHeight'); // 横向滚动条高度 var scrollHeight = that.layMain.height() - that.layMain.prop('clientHeight'); // 横向滚动条高度
var getScrollWidth = that.getScrollWidth(that.layMain[0]); // 获取主容器滚动条宽度,如果有的话 var getScrollWidth = that.getScrollWidth(that.layMain[0]); // 获取主容器滚动条宽度,如果有的话
var outWidth = layMainTable.outerWidth() - that.layMain.width(); // 表格内容器的超出宽度 var outWidth = layMainTable.outerWidth() - that.layMain.width(); // 表格内容器的超出宽度
// 添加补丁 // 添加补丁
var addPatch = function(elem){ var addPatch = function(elem){
if(scollWidth && scollHeight){ if(scrollWidth && scrollHeight){
elem = elem.eq(0); elem = elem.eq(0);
if(!elem.find('.layui-table-patch')[0]){ if(!elem.find('.layui-table-patch')[0]){
var patchElem = $('<th class="layui-table-patch"><div class="layui-table-cell"></div></th>'); // 补丁元素 var patchElem = $('<th class="layui-table-patch"><div class="layui-table-cell"></div></th>'); // 补丁元素
patchElem.find('div').css({ patchElem.find('div').css({
width: scollWidth width: scrollWidth
}); });
elem.find('tr').append(patchElem); elem.find('tr').append(patchElem);
} }
@ -1819,7 +1817,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
// 固定列区域高度 // 固定列区域高度
var mainHeight = that.layMain.height(); var mainHeight = that.layMain.height();
var fixHeight = mainHeight - scollHeight; var fixHeight = mainHeight - scrollHeight;
that.layFixed.find(ELEM_BODY).css( that.layFixed.find(ELEM_BODY).css(
'height', 'height',
@ -1834,7 +1832,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
](HIDE); ](HIDE);
// 操作栏 // 操作栏
that.layFixRight.css('right', scollWidth - 1); that.layFixRight.css('right', scrollWidth - 1);
}; };
// 事件处理 // 事件处理
@ -1878,6 +1876,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
layui.stope(e); layui.stope(e);
_DOC.trigger('table.tool.panel.remove'); _DOC.trigger('table.tool.panel.remove');
layer.close(that.tipsIndex);
switch(events){ switch(events){
case 'LAYTABLE_COLS': // 筛选列 case 'LAYTABLE_COLS': // 筛选列
@ -2072,6 +2071,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
dict.rule.style.width = setWidth + 'px'; dict.rule.style.width = setWidth + 'px';
thatTable.setGroupWidth(thisTable.eventMoveElem); thatTable.setGroupWidth(thisTable.eventMoveElem);
layer.close(that.tipsIndex);
} }
} }
}).on('mouseup', function(e){ }).on('mouseup', function(e){
@ -2319,7 +2319,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
].join(','); ].join(',');
if( $(e.target).is(UNROW) || $(e.target).closest(UNROW)[0]){ if( $(e.target).is(UNROW) || $(e.target).closest(UNROW)[0]){
return; return;
}; }
setRowEvent.call(this, 'row'); setRowEvent.call(this, 'row');
}).on('dblclick', 'tr', function(){ // 双击行 }).on('dblclick', 'tr', function(){ // 双击行
setRowEvent.call(this, 'rowDouble'); setRowEvent.call(this, 'rowDouble');
@ -2463,14 +2463,44 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
var elemCell = td.children(ELEM_CELL); var elemCell = td.children(ELEM_CELL);
var ELEM_CELL_C = 'layui-table-cell-c'; var ELEM_CELL_C = 'layui-table-cell-c';
var elemCellClose = $('<i class="layui-icon layui-icon-up '+ ELEM_CELL_C +'">'); var elemCellClose = $('<i class="layui-icon layui-icon-up '+ ELEM_CELL_C +'">');
var expandedMode = col.expandedMode || options.cellExpandedMode;
// 展开风格
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.elem.find('.'+ ELEM_CELL_C).trigger('click');
// 设置当前单元格展开宽度 // 设置当前单元格展开宽度
that.cssRules(key, function(item){ that.cssRules(key, function(item){
var width = item.style.width; var width = item.style.width;
var expandedWidth = col.expandedWidth || (that.elem.width() / 3); var expandedWidth = col.expandedWidth || options.cellExpandedWidth;
// 展开后的宽度不能小于当前宽度 // 展开后的宽度不能小于当前宽度
if(expandedWidth < parseFloat(width)) expandedWidth = parseFloat(width); if(expandedWidth < parseFloat(width)) expandedWidth = parseFloat(width);
@ -2501,6 +2531,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
}); });
$this.remove(); $this.remove();
}); });
}
othis.remove(); othis.remove();
layui.stope(e); layui.stope(e);
@ -2803,6 +2834,20 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
if(device.ie) return hint.error('IE_NOT_SUPPORT_EXPORTS'); if(device.ie) return hint.error('IE_NOT_SUPPORT_EXPORTS');
// 处理 treeTable 数据
if (config.tree && config.tree.view) {
try {
data = $.extend(true, [], table.cache[id]);
data = (function fn(data) {
return data.reduce(function (acc, obj){
var children = obj.children || [];
delete obj.children;
return acc.concat(obj, fn(children));
}, []);
})(Array.from(data));
} catch (e) {}
}
alink.href = 'data:'+ textType +';charset=utf-8,\ufeff'+ encodeURIComponent(function(){ alink.href = 'data:'+ textType +';charset=utf-8,\ufeff'+ encodeURIComponent(function(){
var dataTitle = []; var dataTitle = [];
var dataMain = []; var dataMain = [];
@ -2984,5 +3029,3 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
exports(MOD_NAME, table); exports(MOD_NAME, table);
}); });

View File

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