` 决定内容修改类型。
+
+### 操作步骤
+
+Layui 使用 Node.js 工具链进行构建与测试,在您参与项目开发之前,请先确保已安装 Node.js 运行环境,推荐版本:`>=20.17.0`
+
+#### 1. 安装依赖
+
+将 Layui 项目 clone 到本地后,请务必使用 `npm ci` 安装依赖,确保所有贡献者与 CI 环境基本一致。
+
+```bash
+npm ci
+```
+
+> 注:若是 Layui 2.x 版本,需使用 `npm install`
+
+#### 2. 开发阶段
+
+依赖安装完毕后,即可启动开发模式
+
+```bash
+npm run dev
+```
+
+开发过程中,我们推荐您在编辑器安装 Prettier 插件,以保持代码风格一致。
+
+完成开发后,请对代码进行静态分析和测试。
+
+```bash
+# lint
+npm run lint
+
+# test
+npm test
+```
+
+上述流程通过,即可提交代码。在 pre-commit 阶段,git hooks 会再次自动检查代码是否符合规范,并自动 lint fix 和格式化代码,对于无法自动 fix 的代码,请按照提示进行手动修改。
+
+#### 3. 提交代码
+
+Layui 遵循 [约定式提交](https://www.conventionalcommits.org/zh-hans/v1.0.0/) 规范,您的提交信息(git commit `message` 和 PR `title`)都应遵循这一规范。
+
+- 创建 PR 时,请在 description 项严格遵循预设的「内容模板」规范填写,以提供必要的信息,如:变更说明、预览地址等。
+- 提交 PR 后,确保已通过 Github CI 检查,若失败,可查看具体原因进行调整。
+
+确保以上所有步骤都符合要求后,即可等待项目成员对您的代码进行 Review 及合并评估。
+
+### 其他参考资料
+
+- [Conventional Commits](https://www.conventionalcommits.org/zh-hans/v1.0.0/)
diff --git a/DISCLAIMER.md b/DISCLAIMER.md
new file mode 100644
index 000000000..76a54113f
--- /dev/null
+++ b/DISCLAIMER.md
@@ -0,0 +1,14 @@
+# Layui 免责声明
+
+> 任何用户在使用由 Layui 技术团队及贡献者(以下统称为「本团队」)研发的系列开源界面组件库(以下简称「Layui」)前,请您仔细阅读并透彻理解本声明。您可以选择不使用 Layui ,若您一旦使用 Layui ,您的使用行为即被视为对本声明全部内容的认可和接受。
+
+1. Layui 是一套免费的开源 Web UI 纯静态组件库,主要用于更高效地开发网页界面。Layui 不具备「互联网接入、网络数据存储、通讯传输以及窃取用户隐私」中的任何一项与用户数据等信息相关的动态功能,Layui 仅是 UI 组件或素材类的本地资源。
+2. Layui 仅为纯静态的 Web 前端代码,不包含任何后台或服务端程序代码;其尊重并保护所有用户的个人隐私权,不窃取任何用户计算机中的信息。更不具备用户数据存储等网络传输功能。
+3. 您承诺秉着合法、合理的原则使用 Layui ,不利用 Layui 进行任何违法、侵害他人合法利益等恶意的行为,亦不将 Layui 运用于任何违反我国法律法规的 Web 平台。
+4. 任何单位或个人因下载使用 Layui 而产生的任何意外、疏忽、合约毁坏、诽谤、版权或知识产权侵犯及其造成的损失 (包括但不限于直接、间接、附带或衍生的损失等),本团队不承担任何法律责任。
+5. 用户明确并同意本声明条款列举的全部内容,对使用 Layui 可能存在的风险和相关后果将完全由用户自行承担,本团队不承担任何法律责任。
+6. 任何单位或个人在阅读本免责声明后,应在《MIT 开源许可证》所允许的范围内进行合法的发布、传播和使用 Layui 等行为,若违反本免责声明条款或违反法律法规所造成的法律责任(包括但不限于民事赔偿和刑事责任),由违约者自行承担。
+7. 本团队对 Layui 拥有知识产权(包括但不限于商标权、专利权、著作权、商业秘密等),上述产品均受到相关法律法规的保护。
+8. 任何单位或个人不得在未经本团队书面授权的情况下对 Layui 本身申请相关的知识产权。
+9. 如果本声明的任何部分被认为无效或不可执行,则该部分将被解释为反映本团队的初衷,其余部分仍具有完全效力。不可执行的部分声明,并不构成我们放弃执行该声明的权利。
+10. 本团队有权随时对本声明条款及附件内容进行单方面的变更,并以消息推送、网页公告等方式予以公布,公布后立即自动生效,无需另行单独通知;若您在本声明内容公告变更后继续使用的,表示您已充分阅读、理解并接受修改后的声明内容。
diff --git a/LICENSE b/LICENSE
index be179b1a0..869eb55c8 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
-MIT License
+The MIT License (MIT)
-Copyright (c) 2016 layui
+Copyright (c) 2016-present Layui contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -9,8 +9,8 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
\ No newline at end of file
+SOFTWARE.
diff --git a/README.en-US.md b/README.en-US.md
new file mode 100644
index 000000000..4911e9001
--- /dev/null
+++ b/README.en-US.md
@@ -0,0 +1,52 @@
+
+
+# Layui
+
+[中文](./README.md) · English
+
+Classic Web UI Component Library
+
+
+
+
+
+
+
+
+
+
+
+
+
+> Layui is an open-source and free web UI component library developed using pure HTML, CSS, and JavaScript. It is designed to facilitate the efficient creation of modern web interfaces. Over the years, it has been widely adopted for its distinctive design style. Layui significantly lowers the barrier for non-front-end developers to build complex web pages, enabling them to implement required page elements and interactions directly within the browser environment without relying on build tools.
+
+## Documentation
+
+- [**Layui 3**](https://github.com/layui/layui/issues/2889) (under development)
+- [**Layui 2**](https://layui.dev/docs/2/)
+
+## Contributors
+
+[Project contributors](https://github.com/layui/layui/graphs/contributors)
+
+## Break with the old and establish the new 🌱
+
+On October 14, 2016, Layui released its first version `1.0.0`, after which it was widely adopted across web platforms.
+
+On October 13, 2021, Layui announced the decommissioning of its original official website (details ) and migrated its documentation site to Gitee Pages. Concurrently, community management and daily maintenance activities were fully transitioned to both Gitee and Github platforms, encouraging users to embrace other superior mainstream frameworks. This move inadvertently led some to believe that Layui had ceased updates. In reality, since then, Layui has remained active on Github and Gitee, never halting updates, progressing from version `2.6.8` at the time to its current latest release.
+
+On April 24, 2023, Layui released version `2.8.0` officially and launched a [new documentation site](https://layui.dev). This marked a sincere comeback and a continuation of its commitment to open-source ideals. We still uphold the perspective expressed in the announcement two years ago, advocating that developers embrace mainstream technologies and nurture an unwavering passion for cutting-edge advancements. **What Layui does is to fill those narrow gaps outside the mainstream**. Although not a mainstream frontend framework, Layui has long transcended being a personal creation of its author, becoming a collective work of all who persist in using it. It continues to underpin numerous projects and represents the efforts of many individuals. As open-source creators, we should walk alongside these dedicated Layui developers.
+
+On October 24, 2025, Layui released version `2.13.0` as the final major version of the 2.x series. This marked a tribute to the bittersweet decade past and officially ushered in a new chapter.
+
+In the future, Layui will steadfastly accompany all those who hold it dear, jointly substantiating the feasibility of the Layui development model.
+
+## License
+
+Layui is released under the [MIT](https://opensource.org/licenses/MIT) license. Other relevant agreements may also refer to the [Disclaimer](https://gitee.com/layui/layui/blob/main/DISCLAIMER.md).
diff --git a/README.md b/README.md
index daec3cb89..7d8d5a5ff 100644
--- a/README.md
+++ b/README.md
@@ -1,112 +1,52 @@
-
-
-
+
+
+# Layui
+
+中文 · [English](./README.en-US.md)
+
+原生态 Web UI 组件库
+
+
+
+
+
+
+
+
+
+
-
- 经典模块化前端UI框架
-
----
-
-Layui 是一款采用自身模块规范编写的国产前端UI框架,遵循原生HTML/CSS/JS的书写与组织形式,门槛极低,拿来即用。其外在极简,却又不失饱满的内在,体积轻盈,组件丰盈,从核心代码到API的每一处细节都经过精心雕琢,非常适合界面的快速开发。layui还很年轻,首个版本发布于2016年金秋,她区别于那些基于MVVM底层的UI框架,却并非逆道而行,而是信奉返璞归真之道,准确地说,她更多是为服务端程序员量身定做,你无需涉足各种前端工具的复杂配置,只需面对浏览器本身,让一切你所需要的元素与交互、从这里信手拈来。
-
-## 返璞归真
-
-Layui 定义为“经典模块化”,并非是自吹她自身有多优秀,而是有意避开当下JS社区的主流方案,试图以最简单的方式去诠释高效!她的所谓经典,是在于对返璞归真的执念 ,她以当前浏览器普通认可的方式去组织模块!我们认为,这恰是符合当下国内绝大多数程序员从旧时代过度到未来新标准的最佳指引。所以 Layui 本身也并不是完全遵循于AMD时代,准确地说,她试图建立自己的模式,所以你会看到:
-
-```
- //layui模块的定义
- layui.define([mods], function(exports){
-
- //……
-
- exports('mod', api);
- });
-
- //layui模块的使用
- layui.use(['mod1', 'mod2'], function(args){
- var mod = layui.mod1;
-
- //……
-
- });
-
-```
-没错,她具备AMD的影子,又并非受限于commonjs的那些条条框框,Layui认为这种轻量的组织方式,比WebPack更符合绝大多数场景。所以她坚持采用经典模块化,也正是能让人避开工具的复杂配置,回归简单,安静高效地撸一会原生态的HTML、CSS、JavaScript。
-
-但是 Layui 又并非是Requirejs那样的模块加载器,而是一款UI解决方案,她与Bootstrap最大的不同恰恰在于她糅合了自身对经典模块化的理解。
-
-
-## 快速上手
-
-获得layui后,将其完整地部署到你的项目目录(或静态资源服务器),你只需要引入下述两个文件:
-
-```
-./layui/css/layui.css
-./layui/layui.js
-```
-
-不用去管其它任何文件。因为他们(比如各模块)都是在最终使用的时候才会自动加载。这是一个基本的入门页面:
-
-```
-
-
-
-
-
- 开始使用Layui
-
-
-
-
-
-
-
-
-
-
-
-```
-
-如果你想快速使用Layui的组件,你还是跟平时一样script标签引入你的js文件,然后在你的js文件中使用layui的组件。但我们更推荐你遵循Layui的模块规范,建立一个自己的模块作为入口:
-
-```
-
-```
-
-上述的 index 即为你 /res/js/modules/ 目录下的 index.js,它的内容应该如下:
-
-```
-/**
- 项目JS主入口
- 以依赖Layui的layer和form模块为例
-**/
-layui.define(['layer', 'form'], function(exports){
- var layer = layui.layer
- ,form = layui.form();
-
- layer.msg('Hello World');
-
- exports('index', {});
-});
-```
-
-好了,不管你采用什么样的方式,从现在开始,尽情地使用Layui吧!但愿这是你的一段轻松而美妙的旅程。
-
-
-## 相关
-[官网](http://www.layui.com/)、[更新日志](https://github.com/sentsin/layui/blob/master/CHANGELOG.md)、[社区交流](http://fly.layui.com)
\ No newline at end of file
+> Layui 是一套开源免费的 Web UI 组件库,采用纯原生态的 HTML CSS JavaScript 开发模式,它为更便捷地构建现代 Web 界面而生。多年来,凭借别具一格的内外风格而被广泛应用。它给非前端开发者极大地降低了构建复杂网页界面的门槛,开发者只需面向浏览器,即可让页面所需呈现的元素与交互,变得信手拈来。
+
+## 使用文档
+
+- [**Layui 3**](https://github.com/layui/layui/issues/2889) (正在开发中)
+- [**Layui 2**](https://layui.dev/docs/2/)
+
+## 项目参与
+
+[项目参与者](https://github.com/layui/layui/graphs/contributors)
+
+## 破旧立新 🌱
+
+2016年10月14日,Layui 发布了 `1.0.0` 首版,此后多年被广泛应用于众多 Web 平台。
+
+2021年10月13日,Layui 发布了原官网下线的公告( 导读 ),并将文档站点切换到了 Gitee Pages,社区及日常维护亦全面转移到了 Gitee 和 Github 平台,以此呼吁大家拥抱其他更好的主流框架,导致大家误以为 Layui 停更了。事实上,自那以后,Layui 仍然在 Github 和 Gitee 保持活跃,并不存在所谓的停止更新,从当时的 `2.6.8` 一直连续迭代到如今的最新版本。
+
+2023年4月24日,Layui 发布了 `2.8.0` 正式版,并上线了[新的文档站点](https://layui.dev),这是一次朴实的回归,更是情怀的延续。 但我们仍然坚持两年前那则公告中的观点, _即仍然推荐大家去拥抱主流,始终保持对前沿技术的无限热爱,是开发者们都应具备的思维属性_。 **而 Layui 所做的,是为填补主流之外的那些略显狭小的空隙**。Layui 虽不是前端主流,但也早已不是作者个人的 Layui,而是所有仍在坚持使用它的人的 Layui,它仍然支撑着许多项目,也代表着许多人的工作。作为开源创作者,应该要为这些坚持者而守望。
+
+2025年10月24日,Layui 发布了 `2.13.0` 重要阶段版本,以致敬过去个中滋味的 10 年,并正式开启一个新的节点。
+
+未来,Layui 会持续陪伴着所有为之热爱的人们,共同去论证 Layui 开发模式的可行性。
+
+## 开源许可
+
+Layui 采用 [MIT](https://opensource.org/licenses/MIT) 许可发布。其他相关协议亦可参考《[免责声明](https://gitee.com/layui/layui/blob/main/DISCLAIMER.md)》。
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 000000000..dccd9a64d
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,20 @@
+# Security Policy
+
+## Supported Versions
+
+Use this section to tell people about which versions of your project are
+currently being supported with security updates.
+
+| Version | Supported |
+| -------- | ------------------ |
+| 3.x | :white_check_mark: |
+| 2.10+ | :white_check_mark: |
+| < 2.10.0 | :x: |
+
+## Reporting a Vulnerability
+
+Use this section to tell people how to report a vulnerability.
+
+Tell them where to go, how often they can expect to get an update on a
+reported vulnerability, what to expect if the vulnerability is accepted or
+declined, etc.
diff --git a/biome.json b/biome.json
new file mode 100644
index 000000000..8b4d6905c
--- /dev/null
+++ b/biome.json
@@ -0,0 +1,41 @@
+{
+ "$schema": "./node_modules/@biomejs/biome/configuration_schema.json",
+ "vcs": {
+ "enabled": true,
+ "clientKind": "git",
+ "useIgnoreFile": true
+ },
+ "files": {
+ "includes": [
+ "src/**",
+ "scripts/**",
+ "tests/**",
+ "*.{js,mjs,cjs}",
+ "!!**/dist"
+ ]
+ },
+ "formatter": {
+ "enabled": true,
+ "indentStyle": "space",
+ "indentWidth": 2
+ },
+ "linter": {
+ "enabled": false,
+ "rules": {
+ "recommended": true
+ }
+ },
+ "javascript": {
+ "formatter": {
+ "quoteStyle": "single"
+ }
+ },
+ "assist": {
+ "enabled": true,
+ "actions": {
+ "source": {
+ "organizeImports": "off"
+ }
+ }
+ }
+}
diff --git a/bower.json b/bower.json
deleted file mode 100644
index e06f37b03..000000000
--- a/bower.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "name": "layui",
- "main": "src/layui.js",
- "version": "1.0.9_rls",
- "homepage": "https://github.com/sentsin/layui",
- "authors": [
- "sentsin "
- ],
- "description": "模块化前端UI框架",
- "moduleType": [
- "amd",
- "globals"
- ],
- "keywords": [
- "layui",
- "ui"
- ],
- "license": "MIT"
-}
diff --git a/build/css/layui.css b/build/css/layui.css
deleted file mode 100644
index e86730331..000000000
--- a/build/css/layui.css
+++ /dev/null
@@ -1,2 +0,0 @@
-/** layui-v1.0.9_rls MIT License By http://www.layui.com */
- .layui-laypage a,a{text-decoration:none}.layui-btn,.layui-inline,img{vertical-align:middle}.layui-btn,.layui-unselect{-webkit-user-select:none;-ms-user-select:none;-moz-user-select:none}.layui-btn,.layui-tree li i,.layui-unselect{-moz-user-select:none}blockquote,body,button,dd,div,dl,dt,form,h1,h2,h3,h4,h5,h6,input,li,ol,p,pre,td,textarea,th,ul{margin:0;padding:0;-webkit-tap-highlight-color:rgba(0,0,0,0)}a:active,a:hover{outline:0}img{display:inline-block;border:none}li{list-style:none}table{border-collapse:collapse;border-spacing:0}h1,h2,h3{font-size:14px;font-weight:400}h4,h5,h6{font-size:100%;font-weight:400}button,input,optgroup,option,select,textarea{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;outline:0}pre{white-space:pre-wrap;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word}::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar-button:vertical{display:none}::-webkit-scrollbar-corner,::-webkit-scrollbar-track{background-color:#e2e2e2}::-webkit-scrollbar-thumb{border-radius:0;background-color:rgba(0,0,0,.3)}::-webkit-scrollbar-thumb:vertical:hover{background-color:rgba(0,0,0,.35)}::-webkit-scrollbar-thumb:vertical:active{background-color:rgba(0,0,0,.38)}@font-face{font-family:layui-icon;src:url(../font/iconfont.eot?v=1.0.9);src:url(../font/iconfont.eot?v=1.0.9#iefix) format('embedded-opentype'),url(../font/iconfont.svg?v=1.0.9#iconfont) format('svg'),url(../font/iconfont.woff?v=1.0.9) format('woff'),url(../font/iconfont.ttf?v=1.0.9) format('truetype')}.layui-icon{font-family:layui-icon!important;font-size:16px;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body{line-height:24px;font:14px Helvetica Neue,Helvetica,PingFang SC,\5FAE\8F6F\96C5\9ED1,Tahoma,Arial,sans-serif}hr{height:1px;margin:10px 0;border:0;background-color:#e2e2e2;clear:both}a{color:#333}a:hover{color:#777}a cite{font-style:normal;*cursor:pointer}.layui-box,.layui-box *{-webkit-box-sizing:content-box!important;-moz-box-sizing:content-box!important;box-sizing:content-box!important}.layui-border-box,.layui-border-box *{-webkit-box-sizing:border-box!important;-moz-box-sizing:border-box!important;box-sizing:border-box!important}.layui-clear{clear:both;*zoom:1}.layui-clear:after{content:'\20';clear:both;*zoom:1;display:block;height:0}.layui-inline{position:relative;display:inline-block;*display:inline;*zoom:1}.layui-edge{position:absolute;width:0;height:0;border-style:dashed;border-color:transparent;overflow:hidden}.layui-elip{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-disabled,.layui-disabled:hover{color:#d2d2d2!important;cursor:not-allowed!important}.layui-circle{border-radius:100%}.layui-show{display:block!important}.layui-hide{display:none!important}.layui-main{position:relative;width:1140px;margin:0 auto}.layui-header{position:relative;z-index:1000;height:60px}.layui-header a:hover{transition:all .5s;-webkit-transition:all .5s}.layui-side{position:fixed;top:0;bottom:0;z-index:999;width:200px;overflow-x:hidden}.layui-side-scroll{width:220px;height:100%;overflow-x:hidden}.layui-body{position:absolute;left:200px;right:0;top:0;bottom:0;z-index:998;width:auto;overflow:hidden;overflow-y:auto;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.layui-layout-admin .layui-header{background-color:#23262E}.layui-layout-admin .layui-side{top:60px;width:200px;overflow-x:hidden}.layui-layout-admin .layui-body{top:60px;bottom:44px}.layui-layout-admin .layui-main{width:auto;margin:0 15px}.layui-layout-admin .layui-footer{position:fixed;left:200px;right:0;bottom:0;height:44px;background-color:#eee}.layui-btn,.layui-input,.layui-select,.layui-textarea,.layui-upload-button{outline:0;-webkit-transition:border-color .3s cubic-bezier(.65,.05,.35,.5);transition:border-color .3s cubic-bezier(.65,.05,.35,.5);-webkit-box-sizing:border-box!important;-moz-box-sizing:border-box!important;box-sizing:border-box!important}.layui-elem-quote{margin-bottom:10px;padding:15px;line-height:22px;border-left:5px solid #009688;border-radius:0 2px 2px 0;background-color:#f2f2f2}.layui-quote-nm{border-color:#e2e2e2;border-style:solid;border-width:1px 1px 1px 5px;background:0 0}.layui-elem-field{margin-bottom:10px;padding:0;border:1px solid #e2e2e2}.layui-elem-field legend{margin-left:20px;padding:0 10px;font-size:20px;font-weight:300}.layui-field-title{margin:10px 0 20px;border:none;border-top:1px solid #e2e2e2}.layui-field-box{padding:10px 15px}.layui-field-title .layui-field-box{padding:10px 0}.layui-progress{position:relative;height:6px;border-radius:20px;background-color:#e2e2e2}.layui-progress-bar{position:absolute;width:0;max-width:100%;height:6px;border-radius:20px;text-align:right;background-color:#5FB878;transition:all .3s;-webkit-transition:all .3s}.layui-progress-big,.layui-progress-big .layui-progress-bar{height:18px;line-height:18px}.layui-progress-text{position:relative;top:-18px;line-height:18px;font-size:12px;color:#666}.layui-progress-big .layui-progress-text{position:static;padding:0 10px;color:#fff}.layui-collapse{border:1px solid #e2e2e2;border-radius:2px}.layui-colla-item{border-top:1px solid #e2e2e2}.layui-colla-item:first-child{border-top:none}.layui-colla-title{position:relative;height:42px;line-height:42px;padding:0 15px 0 35px;color:#333;background-color:#f2f2f2;cursor:pointer}.layui-colla-content{display:none;padding:10px 15px;line-height:22px;border-top:1px solid #e2e2e2;color:#666}.layui-colla-icon{position:absolute;left:15px;top:0;font-size:14px}.layui-bg-red{background-color:#FF5722}.layui-bg-orange{background-color:#F7B824}.layui-bg-green{background-color:#009688}.layui-bg-cyan{background-color:#2F4056}.layui-bg-blue{background-color:#1E9FFF}.layui-bg-black{background-color:#393D49}.layui-bg-gray{background-color:#eee}.layui-word-aux{font-size:12px;color:#999;padding:0 5px}.layui-btn{display:inline-block;height:38px;line-height:38px;padding:0 18px;background-color:#009688;color:#fff;white-space:nowrap;text-align:center;font-size:14px;border:none;border-radius:2px;cursor:pointer;opacity:.9;filter:alpha(opacity=90)}.layui-btn:hover{opacity:.8;filter:alpha(opacity=80);color:#fff}.layui-btn:active{opacity:1;filter:alpha(opacity=100)}.layui-btn+.layui-btn{margin-left:10px}.layui-btn-radius{border-radius:100px}.layui-btn .layui-icon{font-size:18px;vertical-align:bottom}.layui-btn-primary{border:1px solid #C9C9C9;background-color:#fff;color:#555}.layui-btn-primary:hover{border-color:#009688;color:#333}.layui-btn-normal{background-color:#1E9FFF}.layui-btn-warm{background-color:#F7B824}.layui-btn-danger{background-color:#FF5722}.layui-btn-disabled,.layui-btn-disabled:active,.layui-btn-disabled:hover{border:1px solid #e6e6e6;background-color:#FBFBFB;color:#C9C9C9;cursor:not-allowed;opacity:1}.layui-btn-big{height:44px;line-height:44px;padding:0 25px;font-size:16px}.layui-btn-small{height:30px;line-height:30px;padding:0 10px;font-size:12px}.layui-btn-small i{font-size:16px!important}.layui-btn-mini{height:22px;line-height:22px;padding:0 5px;font-size:12px}.layui-btn-mini i{font-size:14px!important}.layui-btn-group{display:inline-block;vertical-align:middle;font-size:0}.layui-btn-group .layui-btn{margin-left:0!important;margin-right:0!important;border-left:1px solid rgba(255,255,255,.5);border-radius:0}.layui-btn-group .layui-btn-primary{border-left:none}.layui-btn-group .layui-btn-primary:hover{border-color:#C9C9C9;color:#009688}.layui-btn-group .layui-btn:first-child{border-left:none;border-radius:2px 0 0 2px}.layui-btn-group .layui-btn-primary:first-child{border-left:1px solid #c9c9c9}.layui-btn-group .layui-btn:last-child{border-radius:0 2px 2px 0}.layui-btn-group .layui-btn+.layui-btn{margin-left:0}.layui-btn-group+.layui-btn-group{margin-left:10px}.layui-input,.layui-select,.layui-textarea{height:38px;line-height:38px;line-height:36px\9;border:1px solid #e6e6e6;background-color:#fff;border-radius:2px}.layui-form-label,.layui-form-mid,.layui-textarea{line-height:20px;position:relative}.layui-input,.layui-textarea{display:block;width:100%;padding-left:10px}.layui-input:hover,.layui-textarea:hover{border-color:#D2D2D2!important}.layui-input:focus,.layui-textarea:focus{border-color:#C9C9C9!important}.layui-textarea{min-height:100px;height:auto;padding:6px 10px;resize:vertical}.layui-select{padding:0 10px}.layui-form input[type=checkbox],.layui-form input[type=radio],.layui-form select{display:none}.layui-form-item{margin-bottom:15px;clear:both;*zoom:1}.layui-form-item:after{content:'\20';clear:both;*zoom:1;display:block;height:0}.layui-form-label{float:left;display:block;padding:9px 15px;width:80px;font-weight:400;text-align:right}.layui-form-item .layui-inline{margin-bottom:5px;margin-right:10px}.layui-input-block,.layui-input-inline{position:relative}.layui-input-block{margin-left:110px;min-height:36px}.layui-input-inline{display:inline-block;vertical-align:middle}.layui-form-item .layui-input-inline{float:left;width:190px;margin-right:10px}.layui-form-text .layui-input-inline{width:auto}.layui-form-mid{float:left;display:block;padding:8px 0;margin-right:10px}.layui-form-danger+.layui-form-select .layui-input,.layui-form-danger:focus{border:1px solid #FF5722!important}.layui-form-select{position:relative}.layui-form-select .layui-input{padding-right:30px;cursor:pointer}.layui-form-select .layui-edge{position:absolute;right:10px;top:50%;margin-top:-3px;cursor:pointer;border-width:6px;border-top-color:#c2c2c2;border-top-style:solid;transition:all .3s;-webkit-transition:all .3s}.layui-form-select dl{display:none;position:absolute;left:0;top:42px;padding:5px 0;z-index:999;min-width:100%;border:1px solid #d2d2d2;max-height:300px;overflow-y:auto;background-color:#fff;border-radius:2px;box-shadow:0 2px 4px rgba(0,0,0,.12);box-sizing:border-box}.layui-form-select dl dd,.layui-form-select dl dt{padding:0 10px;line-height:36px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.layui-form-select dl dt{font-size:12px;color:#999}.layui-form-select dl dd{cursor:pointer}.layui-form-select dl dd:hover{background-color:#f2f2f2}.layui-form-select .layui-select-group dd{padding-left:20px}.layui-form-select dl dd.layui-this{background-color:#5FB878;color:#fff}.layui-form-checkbox,.layui-form-select dl dd.layui-disabled{background-color:#fff}.layui-form-selected dl{display:block}.layui-form-checkbox,.layui-form-checkbox *,.layui-form-radio,.layui-form-radio *,.layui-form-switch{display:inline-block;vertical-align:middle}.layui-form-selected .layui-edge{margin-top:-9px;-webkit-transform:rotate(180deg);transform:rotate(180deg);margin-top:-3px\9}:root .layui-form-selected .layui-edge{margin-top:-9px\0/IE9}.layui-select-none{margin:5px 0;text-align:center;color:#999}.layui-select-disabled .layui-disabled{border-color:#eee!important}.layui-select-disabled .layui-edge{border-top-color:#d2d2d2}.layui-form-checkbox{position:relative;height:30px;line-height:28px;margin-right:10px;padding-right:30px;border:1px solid #d2d2d2;cursor:pointer;font-size:0;border-radius:2px;-webkit-transition:.1s linear;transition:.1s linear;box-sizing:border-box!important}.layui-form-checkbox:hover{border:1px solid #c2c2c2}.layui-form-checkbox span{padding:0 10px;height:100%;font-size:14px;background-color:#d2d2d2;color:#fff;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.layui-form-checkbox:hover span{background-color:#c2c2c2}.layui-form-checkbox i{position:absolute;right:0;width:30px;color:#fff;font-size:20px;text-align:center}.layui-form-checkbox:hover i{color:#c2c2c2}.layui-form-checked,.layui-form-checked:hover{border-color:#5FB878}.layui-form-checked span,.layui-form-checked:hover span{background-color:#5FB878}.layui-form-checked i,.layui-form-checked:hover i{color:#5FB878}.layui-form-item .layui-form-checkbox{margin-top:4px}.layui-form-checkbox[lay-skin=primary]{height:auto!important;line-height:normal!important;border:none!important;margin-right:0;padding-right:0;background:0 0}.layui-form-checkbox[lay-skin=primary] span{float:right;padding-right:15px;line-height:18px;background:0 0;color:#666}.layui-form-checkbox[lay-skin=primary] i{position:relative;top:0;width:16px;line-height:16px;border:1px solid #d2d2d2;font-size:12px;border-radius:2px;background-color:#fff;-webkit-transition:.1s linear;transition:.1s linear}.layui-form-checkbox[lay-skin=primary]:hover i{border-color:#5FB878;color:#fff}.layui-form-checked[lay-skin=primary] i{border-color:#5FB878;background-color:#5FB878;color:#fff}.layui-checkbox-disbaled[lay-skin=primary] span{background:0 0!important}.layui-checkbox-disbaled[lay-skin=primary]:hover i{border-color:#d2d2d2}.layui-form-item .layui-form-checkbox[lay-skin=primary]{margin-top:10px}.layui-form-switch{position:relative;height:22px;line-height:22px;width:42px;padding:0 5px;margin-top:8px;border:1px solid #d2d2d2;border-radius:20px;cursor:pointer;background-color:#fff;-webkit-transition:.1s linear;transition:.1s linear}.layui-form-switch i{position:absolute;left:5px;top:3px;width:16px;height:16px;border-radius:20px;background-color:#d2d2d2;-webkit-transition:.1s linear;transition:.1s linear}.layui-form-switch em{position:absolute;right:5px;top:0;width:25px;padding:0!important;text-align:center!important;color:#999!important;font-style:normal!important;font-size:12px}.layui-form-onswitch{border-color:#5FB878;background-color:#5FB878}.layui-form-onswitch i{left:32px;background-color:#fff}.layui-form-onswitch em{left:5px;right:auto;color:#fff!important}.layui-checkbox-disbaled{border-color:#e2e2e2!important}.layui-checkbox-disbaled span{background-color:#e2e2e2!important}.layui-checkbox-disbaled:hover i{color:#fff!important}.layui-form-radio{line-height:28px;margin:6px 10px 0 0;padding-right:10px;cursor:pointer;font-size:0}.layui-form-radio i{margin-right:8px;font-size:22px;color:#c2c2c2}.layui-form-radio span{font-size:14px}.layui-form-radio i:hover,.layui-form-radioed i{color:#5FB878}.layui-radio-disbaled i{color:#e2e2e2!important}.layui-form-pane .layui-form-label{width:110px;padding:8px 15px;height:38px;line-height:20px;border:1px solid #e6e6e6;border-radius:2px 0 0 2px;text-align:center;background-color:#FBFBFB;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;-webkit-box-sizing:border-box!important;-moz-box-sizing:border-box!important;box-sizing:border-box!important}.layui-form-pane .layui-input-inline{margin-left:-1px}.layui-form-pane .layui-input-block{margin-left:110px;left:-1px}.layui-form-pane .layui-input{border-radius:0 2px 2px 0}.layui-form-pane .layui-form-text .layui-form-label{float:none;width:100%;border-right:1px solid #e6e6e6;border-radius:2px;-webkit-box-sizing:border-box!important;-moz-box-sizing:border-box!important;box-sizing:border-box!important;text-align:left}.layui-laypage button,.layui-laypage input,.layui-nav{-webkit-box-sizing:border-box!important;-moz-box-sizing:border-box!important}.layui-form-pane .layui-form-text .layui-input-inline{display:block;margin:0;top:-1px;clear:both}.layui-form-pane .layui-form-text .layui-input-block{margin:0;left:0;top:-1px}.layui-form-pane .layui-form-text .layui-textarea{min-height:100px;border-radius:0 0 2px 2px}.layui-form-pane .layui-form-checkbox{margin:4px 0 4px 10px}.layui-form-pane .layui-form-radio,.layui-form-pane .layui-form-switch{margin-top:6px;margin-left:10px}.layui-form-pane .layui-form-item[pane]{position:relative;border:1px solid #e6e6e6}.layui-form-pane .layui-form-item[pane] .layui-form-label{position:absolute;left:0;top:0;height:100%;border-width:0 1px 0 0}.layui-form-pane .layui-form-item[pane] .layui-input-inline{margin-left:110px}.layui-layedit{border:1px solid #d2d2d2;border-radius:2px}.layui-layedit-tool{padding:3px 5px;border-bottom:1px solid #e2e2e2;font-size:0}.layedit-tool-fixed{position:fixed;top:0;border-top:1px solid #e2e2e2}.layui-layedit-tool .layedit-tool-mid,.layui-layedit-tool .layui-icon{display:inline-block;vertical-align:middle;text-align:center;font-size:14px}.layui-layedit-tool .layui-icon{position:relative;width:32px;height:30px;line-height:30px;margin:3px 5px;color:#777;cursor:pointer;border-radius:2px}.layui-layedit-tool .layui-icon:hover{color:#393D49}.layui-layedit-tool .layui-icon:active{color:#000}.layui-layedit-tool .layedit-tool-active{background-color:#e2e2e2;color:#000}.layui-layedit-tool .layui-disabled,.layui-layedit-tool .layui-disabled:hover{color:#d2d2d2;cursor:not-allowed}.layui-layedit-tool .layedit-tool-mid{width:1px;height:18px;margin:0 10px;background-color:#d2d2d2}.layedit-tool-html{width:50px!important;font-size:30px!important}.layedit-tool-b,.layedit-tool-code,.layedit-tool-help{font-size:16px!important}.layedit-tool-d,.layedit-tool-face,.layedit-tool-image,.layedit-tool-unlink{font-size:18px!important}.layedit-tool-image input{position:absolute;font-size:0;left:0;top:0;width:100%;height:100%;opacity:.01;filter:Alpha(opacity=1);cursor:pointer}.layui-layedit-iframe iframe{display:block;width:100%}#LAY_layedit_code{overflow:hidden}.layui-table{width:100%;margin:10px 0;background-color:#fff}.layui-table tr{transition:all .3s;-webkit-transition:all .3s}.layui-table thead tr{background-color:#f2f2f2}.layui-table th{text-align:left}.layui-table td,.layui-table th{padding:9px 15px;min-height:20px;line-height:20px;border:1px solid #e2e2e2;font-size:14px}.layui-table tr:hover,.layui-table[lay-even] tr:nth-child(even){background-color:#f8f8f8}.layui-table[lay-skin=line],.layui-table[lay-skin=row]{border:1px solid #e2e2e2}.layui-table[lay-skin=line] td,.layui-table[lay-skin=line] th{border:none;border-bottom:1px solid #e2e2e2}.layui-table[lay-skin=row] td,.layui-table[lay-skin=row] th{border:none;border-right:1px solid #e2e2e2}.layui-table[lay-skin=nob] td,.layui-table[lay-skin=nob] th{border:none}.layui-upload-button{position:relative;display:inline-block;vertical-align:middle;min-width:60px;height:38px;line-height:38px;border:1px solid #DFDFDF;border-radius:2px;overflow:hidden;background-color:#fff;color:#666}.layui-upload-button:hover{border:1px solid #aaa;color:#333}.layui-upload-button:active{border:1px solid #4CAF50;color:#000}.layui-upload-button input,.layui-upload-file{opacity:.01;filter:Alpha(opacity=1);cursor:pointer}.layui-upload-button input{position:absolute;left:0;top:0;z-index:10;font-size:100px;width:100%;height:100%}.layui-upload-icon{display:block;margin:0 15px;text-align:center}.layui-upload-icon i{margin-right:5px;vertical-align:top;font-size:20px;color:#5FB878}.layui-upload-iframe{position:absolute;width:0;height:0;border:0;visibility:hidden}.layui-upload-enter{border:1px solid #009E94;background-color:#009E94;color:#fff;-webkit-transform:scale(1.1);transform:scale(1.1)}.layui-upload-enter .layui-upload-icon,.layui-upload-enter .layui-upload-icon i{color:#fff}.layui-flow-more{margin:10px 0;text-align:center;color:#999;font-size:14px}.layui-flow-more a{height:32px;line-height:32px}.layui-flow-more a *{display:inline-block;vertical-align:top}.layui-flow-more a cite{padding:0 20px;border-radius:3px;background-color:#eee;color:#333;font-style:normal}.layui-flow-more a cite:hover{opacity:.8}.layui-flow-more a i{font-size:30px;color:#737383}.layui-laypage{display:inline-block;*display:inline;*zoom:1;vertical-align:middle;margin:10px 0;font-size:0}.layui-laypage>:first-child,.layui-laypage>:first-child em{border-radius:2px 0 0 2px}.layui-laypage>:last-child,.layui-laypage>:last-child em{border-radius:0 2px 2px 0}.layui-laypage a,.layui-laypage span{display:inline-block;*display:inline;*zoom:1;vertical-align:middle;padding:0 15px;border:1px solid #e2e2e2;height:28px;line-height:28px;margin:0 -1px 5px 0;background-color:#fff;color:#333;font-size:12px}.layui-laypage em{font-style:normal}.layui-laypage span{color:#999;font-weight:700}.layui-laypage .layui-laypage-curr{position:relative}.layui-laypage .layui-laypage-curr em{position:relative;color:#fff;font-weight:400}.layui-laypage .layui-laypage-curr .layui-laypage-em{position:absolute;left:-1px;top:-1px;padding:1px;width:100%;height:100%;background-color:#009688}.layui-laypage-em{border-radius:2px}.layui-laypage-next em,.layui-laypage-prev em{font-family:Sim sun;font-size:16px}.layui-laypage .layui-laypage-total{height:30px;line-height:30px;margin-left:1px;border:none;font-weight:400}.layui-laypage button,.layui-laypage input{height:30px;line-height:30px;border:1px solid #e2e2e2;border-radius:2px;vertical-align:top;background-color:#fff;box-sizing:border-box!important}.layui-laypage input{width:50px;margin:0 5px;text-align:center}.layui-laypage button{margin-left:5px;padding:0 15px;cursor:pointer}.layui-code{position:relative;margin:10px 0;padding:15px;line-height:20px;border:1px solid #ddd;border-left-width:6px;background-color:#F2F2F2;color:#333;font-family:Courier New;font-size:12px}.layui-tree{line-height:26px}.layui-tree li{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-tree li .layui-tree-spread,.layui-tree li a{display:inline-block;vertical-align:top;height:26px;*display:inline;*zoom:1;cursor:pointer}.layui-tree li a{font-size:0}.layui-tree li a i{font-size:16px}.layui-tree li a cite{padding:0 6px;font-size:14px;font-style:normal}.layui-tree li i{padding-left:6px;color:#333}.layui-tree li .layui-tree-check{font-size:13px}.layui-tree li .layui-tree-check:hover{color:#009E94}.layui-tree li ul{display:none;margin-left:20px}.layui-tree li .layui-tree-enter{line-height:24px;border:1px dotted #000}.layui-tree-drag{display:none;position:absolute;left:-666px;top:-666px;background-color:#f2f2f2;padding:5px 10px;border:1px dotted #000;white-space:nowrap}.layui-tree-drag i{padding-right:5px}.layui-nav{position:relative;padding:0 20px;background-color:#393D49;color:#c2c2c2;border-radius:2px;font-size:0;box-sizing:border-box!important}.layui-nav *{font-size:14px}.layui-nav .layui-nav-item{position:relative;display:inline-block;*display:inline;*zoom:1;vertical-align:middle;line-height:60px}.layui-nav .layui-nav-item a{display:block;padding:0 20px;color:#c2c2c2;transition:all .3s;-webkit-transition:all .3s}.layui-nav .layui-this:after,.layui-nav-bar,.layui-nav-tree .layui-nav-itemed:after{position:absolute;left:0;top:0;width:0;height:5px;background-color:#5FB878;transition:all .2s;-webkit-transition:all .2s}.layui-nav-bar{z-index:1000}.layui-nav .layui-nav-item a:hover,.layui-nav .layui-this a{color:#fff}.layui-nav .layui-this:after{content:'';top:auto;bottom:0;width:100%}.layui-nav .layui-nav-more{content:'';width:0;height:0;border-style:solid dashed dashed;border-color:#c2c2c2 transparent transparent;overflow:hidden;cursor:pointer;transition:all .2s;-webkit-transition:all .2s;position:absolute;top:28px;right:3px;border-width:6px}.layui-nav .layui-nav-mored,.layui-nav-itemed .layui-nav-more{top:22px;border-style:dashed dashed solid;border-color:transparent transparent #c2c2c2}.layui-nav-child{display:none;position:absolute;left:0;top:65px;min-width:100%;line-height:36px;padding:5px 0;box-shadow:0 2px 4px rgba(0,0,0,.12);border:1px solid #d2d2d2;background-color:#fff;z-index:100;border-radius:2px;white-space:nowrap}.layui-nav .layui-nav-child a{color:#333}.layui-nav .layui-nav-child a:hover{background-color:#f2f2f2;color:#333}.layui-nav-child dd{position:relative}.layui-nav-child dd.layui-this{background-color:#5FB878;color:#fff}.layui-nav-child dd.layui-this a{color:#fff}.layui-nav-child dd.layui-this:after{display:none}.layui-nav-tree{width:200px;padding:0}.layui-nav-tree .layui-nav-item{display:block;width:100%;line-height:45px}.layui-nav-tree .layui-nav-item a{height:45px;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-nav-tree .layui-nav-item a:hover{background-color:#4E5465}.layui-nav-tree .layui-nav-child dd.layui-this,.layui-nav-tree .layui-this,.layui-nav-tree .layui-this>a,.layui-nav-tree .layui-this>a:hover{background-color:#009688;color:#fff}.layui-nav-tree .layui-this:after{display:none}.layui-nav-itemed>a,.layui-nav-tree .layui-nav-title a,.layui-nav-tree .layui-nav-title a:hover{background-color:#2B2E37!important;color:#fff!important}.layui-nav-tree .layui-nav-bar{width:5px;height:0;background-color:#009688}.layui-nav-tree .layui-nav-child{position:relative;z-index:0;top:0;border:none;box-shadow:none}.layui-nav-tree .layui-nav-child a{height:40px;line-height:40px;color:#c2c2c2}.layui-nav-tree .layui-nav-child,.layui-nav-tree .layui-nav-child a:hover{background:0 0;color:#fff}.layui-nav-tree .layui-nav-more{top:20px;right:10px}.layui-nav-itemed .layui-nav-more{top:14px}.layui-nav-itemed .layui-nav-child{display:block;padding:0}.layui-nav-side{position:fixed;top:0;bottom:0;left:0;overflow-x:hidden;z-index:999}.layui-breadcrumb{visibility:hidden;font-size:0}.layui-breadcrumb a{padding-right:8px;line-height:22px;font-size:14px;color:#333!important}.layui-breadcrumb a:hover{color:#01AAED!important}.layui-breadcrumb a cite,.layui-breadcrumb a span{color:#666;cursor:text;font-style:normal}.layui-breadcrumb a span{padding-left:8px;font-family:Sim sun}.layui-tab{margin:10px 0;text-align:left!important}.layui-fixbar li,.layui-tab-bar,.layui-tab-title li,.layui-util-face ul li{cursor:pointer;text-align:center}.layui-tab[overflow]>.layui-tab-title{overflow:hidden}.layui-tab-title{position:relative;left:0;height:40px;white-space:nowrap;font-size:0;border-bottom:1px solid #e2e2e2;transition:all .2s;-webkit-transition:all .2s}.layui-tab-title li{display:inline-block;*display:inline;*zoom:1;vertical-align:middle;font-size:14px;transition:all .2s;-webkit-transition:all .2s;position:relative;line-height:40px;min-width:65px;padding:0 10px}.layui-tab-title li a{display:block}.layui-tab-title .layui-this{color:#000}.layui-tab-title .layui-this:after{position:absolute;left:0;top:0;content:'';width:100%;height:41px;border:1px solid #e2e2e2;border-bottom-color:#fff;border-radius:2px 2px 0 0;-webkit-box-sizing:border-box!important;-moz-box-sizing:border-box!important;box-sizing:border-box!important;pointer-events:none}.layui-tab-bar{position:absolute;right:0;top:0;z-index:10;width:30px;height:39px;line-height:39px;border:1px solid #e2e2e2;border-radius:2px;background-color:#fff}.layui-tab-bar .layui-icon{position:relative;display:inline-block;top:3px;transition:all .3s;-webkit-transition:all .3s}.layui-tab-item,.layui-util-face .layui-layer-TipsG{display:none}.layui-tab-more{padding-right:30px;height:auto;white-space:normal}.layui-tab-more li.layui-this:after{border-bottom-color:#e2e2e2;border-radius:2px}.layui-tab-more .layui-tab-bar .layui-icon{top:-2px;top:3px\9;-webkit-transform:rotate(180deg);transform:rotate(180deg)}:root .layui-tab-more .layui-tab-bar .layui-icon{top:-2px\0/IE9}.layui-tab-content{padding:10px}.layui-tab-title li .layui-tab-close{position:relative;margin-left:8px;top:1px;color:#c2c2c2;transition:all .2s;-webkit-transition:all .2s}.layui-tab-title li .layui-tab-close:hover{border-radius:2px;background-color:#FF5722;color:#fff}.layui-tab-brief>.layui-tab-title .layui-this{color:#009688}.layui-tab-brief>.layui-tab-more li.layui-this:after,.layui-tab-brief>.layui-tab-title .layui-this:after{border:none;border-radius:0;border-bottom:3px solid #5FB878}.layui-tab-brief[overflow]>.layui-tab-title .layui-this:after{top:-1px}.layui-tab-card{border:1px solid #e2e2e2;border-radius:2px;box-shadow:0 2px 5px 0 rgba(0,0,0,.1)}.layui-tab-card>.layui-tab-title{background-color:#f2f2f2}.layui-tab-card>.layui-tab-title li{margin-right:-1px;margin-left:-1px}.layui-tab-card>.layui-tab-title .layui-this{background-color:#fff}.layui-tab-card>.layui-tab-title .layui-this:after{border-top:none;border-width:1px;border-bottom-color:#fff}.layui-tab-card>.layui-tab-title .layui-tab-bar{height:40px;line-height:40px;border-radius:0;border-top:none;border-right:none}.layui-tab-card>.layui-tab-more .layui-this{background:0 0;color:#5FB878}.layui-tab-card>.layui-tab-more .layui-this:after{border:none}.layui-fixbar{position:fixed;right:15px;bottom:15px;z-index:9999}.layui-fixbar li{width:50px;height:50px;line-height:50px;margin-bottom:1px;font-size:30px;background-color:#9F9F9F;color:#fff;border-radius:2px;opacity:.95}.layui-fixbar li:hover{opacity:.85}.layui-fixbar li:active{opacity:1}.layui-fixbar .layui-fixbar-top{display:none;font-size:40px}body .layui-util-face{border:none;background:0 0}body .layui-util-face .layui-layer-content{padding:0;background-color:#fff;color:#666;box-shadow:none}.layui-util-face ul{position:relative;width:372px;padding:10px;border:1px solid #D9D9D9;background-color:#fff;box-shadow:0 0 20px rgba(0,0,0,.2)}.layui-util-face ul li{float:left;border:1px solid #e8e8e8;height:22px;width:26px;overflow:hidden;margin:-1px 0 0 -1px;padding:4px 2px}.layui-util-face ul li:hover{position:relative;z-index:2;border:1px solid #eb7350;background:#fff9ec}.layui-anim{-webkit-animation-duration:.3s;animation-duration:.3s;-webkit-animation-fill-mode:both;animation-fill-mode:both}.layui-anim-loop{-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}@-webkit-keyframes layui-rotate{from{-webkit-transform:rotate(0)}to{-webkit-transform:rotate(360deg)}}@keyframes layui-rotate{from{transform:rotate(0)}to{transform:rotate(360deg)}}.layui-anim-rotate{-webkit-animation-name:layui-rotate;animation-name:layui-rotate;-webkit-animation-duration:1s;animation-duration:1s;-webkit-animation-timing-function:linear;animation-timing-function:linear}@-webkit-keyframes layui-up{from{-webkit-transform:translate3d(0,100%,0);opacity:.3}to{-webkit-transform:translate3d(0,0,0);opacity:1}}@keyframes layui-up{from{transform:translate3d(0,100%,0);opacity:.3}to{transform:translate3d(0,0,0);opacity:1}}.layui-anim-up{-webkit-animation-name:layui-up;animation-name:layui-up}@-webkit-keyframes layui-upbit{from{-webkit-transform:translate3d(0,30px,0);opacity:.3}to{-webkit-transform:translate3d(0,0,0);opacity:1}}@keyframes layui-upbit{from{transform:translate3d(0,30px,0);opacity:.3}to{transform:translate3d(0,0,0);opacity:1}}.layui-anim-upbit{-webkit-animation-name:layui-upbit;animation-name:layui-upbit}@-webkit-keyframes layui-scale{0%{opacity:.3;-webkit-transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1)}}@keyframes layui-scale{0%{opacity:.3;-ms-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-ms-transform:scale(1);transform:scale(1)}}.layui-anim-scale{-webkit-animation-name:layui-scale;animation-name:layui-scale}@-webkit-keyframes layui-scale-spring{0%{opacity:.5;-webkit-transform:scale(.5)}80%{opacity:.8;-webkit-transform:scale(1.1)}100%{opacity:1;-webkit-transform:scale(1)}}@keyframes layui-scale-spring{0%{opacity:.5;-ms-transform:scale(.5);transform:scale(.5)}80%{opacity:.8;-ms-transform:scale(1.1);transform:scale(1.1)}100%{opacity:1;-ms-transform:scale(1);transform:scale(1)}}.layui-anim-scaleSpring{-webkit-animation-name:layui-scale-spring;animation-name:layui-scale-spring}@media screen and (max-width:450px){.layui-form-item .layui-form-label{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-form-item .layui-inline{display:block;margin-right:0;margin-bottom:20px;clear:both}.layui-form-item .layui-inline:after{content:'\20';clear:both;display:block;height:0}.layui-form-item .layui-input-inline{display:block;float:none;left:-3px;width:auto;margin:0 0 10px 112px}.layui-form-item .layui-input-inline+.layui-form-mid{margin-left:110px;top:-5px;padding:0}.layui-form-item .layui-form-checkbox{margin-right:5px;margin-bottom:5px}}
\ No newline at end of file
diff --git a/build/css/layui.mobile.css b/build/css/layui.mobile.css
deleted file mode 100644
index 2a238cda3..000000000
--- a/build/css/layui.mobile.css
+++ /dev/null
@@ -1,2 +0,0 @@
-/** layui-v1.0.9_rls MIT License By http://www.layui.com */
- blockquote,body,button,dd,div,dl,dt,form,h1,h2,h3,h4,h5,h6,input,legend,li,ol,p,td,textarea,th,ul{margin:0;padding:0;-webkit-tap-highlight-color:rgba(0,0,0,0)}html{font:12px 'Helvetica Neue','PingFang SC',STHeitiSC-Light,Helvetica,Arial,sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}a,button,input{-webkit-tap-highlight-color:rgba(255,0,0,0)}a{text-decoration:none;background:0 0}a:active,a:hover{outline:0}table{border-collapse:collapse;border-spacing:0}li{list-style:none}b,strong{font-weight:700}h1,h2,h3,h4,h5,h6{font-weight:500}address,cite,dfn,em,var{font-style:normal}dfn{font-style:italic}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}img{border:0;vertical-align:bottom}.layui-inline,input,label{vertical-align:middle}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0;outline:0}button,select{text-transform:none}select{-webkit-appearance:none;border:none}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}@font-face{font-family:layui-icon;src:url(../font/iconfont.eot?v=1.0.7);src:url(../font/iconfont.eot?v=1.0.7#iefix) format('embedded-opentype'),url(../font/iconfont.woff?v=1.0.7) format('woff'),url(../font/iconfont.ttf?v=1.0.7) format('truetype'),url(../font/iconfont.svg?v=1.0.7#iconfont) format('svg')}.layui-icon{font-family:layui-icon!important;font-size:16px;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.layui-box,.layui-box *{-webkit-box-sizing:content-box!important;-moz-box-sizing:content-box!important;box-sizing:content-box!important}.layui-border-box,.layui-border-box *{-webkit-box-sizing:border-box!important;-moz-box-sizing:border-box!important;box-sizing:border-box!important}.layui-inline{position:relative;display:inline-block;*display:inline;*zoom:1}.layui-edge,.layui-upload-iframe{position:absolute;width:0;height:0}.layui-edge{border-style:dashed;border-color:transparent;overflow:hidden}.layui-elip{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-unselect{-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.layui-disabled,.layui-disabled:active{background-color:#d2d2d2!important;color:#fff!important;cursor:not-allowed!important}.layui-circle{border-radius:100%}.layui-show{display:block!important}.layui-hide{display:none!important}.layui-upload-iframe{border:0;visibility:hidden}.layui-upload-enter{border:1px solid #009E94;background-color:#009E94;color:#fff;-webkit-transform:scale(1.1);transform:scale(1.1)}@-webkit-keyframes layui-m-anim-scale{0%{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}@keyframes layui-m-anim-scale{0%{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}.layui-m-anim-scale{animation-name:layui-m-anim-scale;-webkit-animation-name:layui-m-anim-scale}@-webkit-keyframes layui-m-anim-up{0%{opacity:0;-webkit-transform:translateY(800px);transform:translateY(800px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes layui-m-anim-up{0%{opacity:0;-webkit-transform:translateY(800px);transform:translateY(800px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}.layui-m-anim-up{-webkit-animation-name:layui-m-anim-up;animation-name:layui-m-anim-up}@-webkit-keyframes layui-m-anim-left{0%{-webkit-transform:translateX(100%);transform:translateX(100%)}100%{-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes layui-m-anim-left{0%{-webkit-transform:translateX(100%);transform:translateX(100%)}100%{-webkit-transform:translateX(0);transform:translateX(0)}}.layui-m-anim-left{-webkit-animation-name:layui-m-anim-left;animation-name:layui-m-anim-left}@-webkit-keyframes layui-m-anim-right{0%{-webkit-transform:translateX(-100%);transform:translateX(-100%)}100%{-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes layui-m-anim-right{0%{-webkit-transform:translateX(-100%);transform:translateX(-100%)}100%{-webkit-transform:translateX(0);transform:translateX(0)}}.layui-m-anim-right{-webkit-animation-name:layui-m-anim-right;animation-name:layui-m-anim-right}@-webkit-keyframes layui-m-anim-lout{0%{-webkit-transform:translateX(0);transform:translateX(0)}100%{-webkit-transform:translateX(-100%);transform:translateX(-100%)}}@keyframes layui-m-anim-lout{0%{-webkit-transform:translateX(0);transform:translateX(0)}100%{-webkit-transform:translateX(-100%);transform:translateX(-100%)}}.layui-m-anim-lout{-webkit-animation-name:layui-m-anim-lout;animation-name:layui-m-anim-lout}@-webkit-keyframes layui-m-anim-rout{0%{-webkit-transform:translateX(0);transform:translateX(0)}100%{-webkit-transform:translateX(100%);transform:translateX(100%)}}@keyframes layui-m-anim-rout{0%{-webkit-transform:translateX(0);transform:translateX(0)}100%{-webkit-transform:translateX(100%);transform:translateX(100%)}}.layui-m-anim-rout{-webkit-animation-name:layui-m-anim-rout;animation-name:layui-m-anim-rout}.layui-m-layer{position:relative;z-index:19891014}.layui-m-layer *{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.layui-m-layermain,.layui-m-layershade{position:fixed;left:0;top:0;width:100%;height:100%}.layui-m-layershade{background-color:rgba(0,0,0,.7);pointer-events:auto}.layui-m-layermain{display:table;font-family:Helvetica,arial,sans-serif;pointer-events:none}.layui-m-layermain .layui-m-layersection{display:table-cell;vertical-align:middle;text-align:center}.layui-m-layerchild{position:relative;display:inline-block;text-align:left;background-color:#fff;font-size:14px;border-radius:5px;box-shadow:0 0 8px rgba(0,0,0,.1);pointer-events:auto;-webkit-overflow-scrolling:touch;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-duration:.2s;animation-duration:.2s}.layui-m-layer0 .layui-m-layerchild{width:90%;max-width:640px}.layui-m-layer1 .layui-m-layerchild{border:none;border-radius:0}.layui-m-layer2 .layui-m-layerchild{width:auto;max-width:260px;min-width:40px;border:none;background:0 0;box-shadow:none;color:#fff}.layui-m-layerchild h3{padding:0 10px;height:60px;line-height:60px;font-size:16px;font-weight:400;border-radius:5px 5px 0 0;text-align:center}.layui-m-layerbtn span,.layui-m-layerchild h3{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-m-layercont{padding:50px 30px;line-height:22px;text-align:center}.layui-m-layer1 .layui-m-layercont{padding:0;text-align:left}.layui-m-layer2 .layui-m-layercont{text-align:center;padding:0;line-height:0}.layui-m-layer2 .layui-m-layercont i{width:25px;height:25px;margin-left:8px;display:inline-block;background-color:#fff;border-radius:100%;-webkit-animation:layui-m-anim-loading 1.4s infinite ease-in-out;animation:layui-m-anim-loading 1.4s infinite ease-in-out;-webkit-animation-fill-mode:both;animation-fill-mode:both}.layui-m-layerbtn,.layui-m-layerbtn span{position:relative;text-align:center;border-radius:0 0 5px 5px}.layui-m-layer2 .layui-m-layercont p{margin-top:20px}@-webkit-keyframes layui-m-anim-loading{0%,100%,80%{transform:scale(0);-webkit-transform:scale(0)}40%{transform:scale(1);-webkit-transform:scale(1)}}@keyframes layui-m-anim-loading{0%,100%,80%{transform:scale(0);-webkit-transform:scale(0)}40%{transform:scale(1);-webkit-transform:scale(1)}}.layui-m-layer2 .layui-m-layercont i:first-child{margin-left:0;-webkit-animation-delay:-.32s;animation-delay:-.32s}.layui-m-layer2 .layui-m-layercont i.layui-m-layerload{-webkit-animation-delay:-.16s;animation-delay:-.16s}.layui-m-layer2 .layui-m-layercont>div{line-height:22px;padding-top:7px;margin-bottom:20px;font-size:14px}.layui-m-layerbtn{display:box;display:-moz-box;display:-webkit-box;width:100%;height:50px;line-height:50px;font-size:0;border-top:1px solid #D0D0D0;background-color:#F2F2F2}.layui-m-layerbtn span{display:block;-moz-box-flex:1;box-flex:1;-webkit-box-flex:1;font-size:14px;cursor:pointer}.layui-m-layerbtn span[yes]{color:#40AFFE}.layui-m-layerbtn span[no]{border-right:1px solid #D0D0D0;border-radius:0 0 0 5px}.layui-m-layerbtn span:active{background-color:#F6F6F6}.layui-m-layerend{position:absolute;right:7px;top:10px;width:30px;height:30px;border:0;font-weight:400;background:0 0;cursor:pointer;-webkit-appearance:none;font-size:30px}.layui-m-layerend::after,.layui-m-layerend::before{position:absolute;left:5px;top:15px;content:'';width:18px;height:1px;background-color:#999;transform:rotate(45deg);-webkit-transform:rotate(45deg);border-radius:3px}.layui-m-layerend::after{transform:rotate(-45deg);-webkit-transform:rotate(-45deg)}body .layui-m-layer .layui-m-layer-footer{position:fixed;width:95%;max-width:100%;margin:0 auto;left:0;right:0;bottom:10px;background:0 0}.layui-m-layer-footer .layui-m-layercont{padding:20px;border-radius:5px 5px 0 0;background-color:rgba(255,255,255,.8)}.layui-m-layer-footer .layui-m-layerbtn{display:block;height:auto;background:0 0;border-top:none}.layui-m-layer-footer .layui-m-layerbtn span{background-color:rgba(255,255,255,.8)}.layui-m-layer-footer .layui-m-layerbtn span[no]{color:#FD482C;border-top:1px solid #c2c2c2;border-radius:0 0 5px 5px}.layui-m-layer-footer .layui-m-layerbtn span[yes]{margin-top:10px;border-radius:5px}body .layui-m-layer .layui-m-layer-msg{width:auto;max-width:90%;margin:0 auto;bottom:-150px;background-color:rgba(0,0,0,.7);color:#fff}.layui-m-layer-msg .layui-m-layercont{padding:10px 20px}
\ No newline at end of file
diff --git a/build/css/modules/code.css b/build/css/modules/code.css
deleted file mode 100644
index 704b8f3d7..000000000
--- a/build/css/modules/code.css
+++ /dev/null
@@ -1,2 +0,0 @@
-/** layui-v1.0.9_rls MIT License By http://www.layui.com */
- html #layuicss-skincodecss{display:none;position:absolute;width:1989px}.layui-code-h3,.layui-code-view{position:relative;font-size:12px}.layui-code-view{display:block;margin:10px 0;padding:0;border:1px solid #ddd;border-left-width:6px;background-color:#F2F2F2;color:#333;font-family:Courier New}.layui-code-h3{padding:0 10px;height:30px;line-height:30px;border-bottom:1px solid #ddd}.layui-code-h3 a{position:absolute;right:10px;top:0;color:#999}.layui-code-view .layui-code-ol{position:relative;overflow:auto}.layui-code-view .layui-code-ol li{position:relative;margin-left:45px;line-height:20px;padding:0 5px;border-left:1px solid #ddd;list-style-type:decimal-leading-zero;*list-style-type:decimal;background-color:#fff}.layui-code-view pre{margin:0}.layui-code-notepad{border:1px solid #0C0C0C;border-left-color:#3F3F3F;background-color:#0C0C0C;color:#C2BE9E}.layui-code-notepad .layui-code-h3{border-bottom:none}.layui-code-notepad .layui-code-ol li{background-color:#3F3F3F;border-left:none}
\ No newline at end of file
diff --git a/build/css/modules/laydate/icon.png b/build/css/modules/laydate/icon.png
deleted file mode 100644
index 5a50673e0..000000000
Binary files a/build/css/modules/laydate/icon.png and /dev/null differ
diff --git a/build/css/modules/laydate/laydate.css b/build/css/modules/laydate/laydate.css
deleted file mode 100644
index c0eec2f81..000000000
--- a/build/css/modules/laydate/laydate.css
+++ /dev/null
@@ -1,2 +0,0 @@
-/** layui-v1.0.9_rls MIT License By http://www.layui.com */
- #layuicss-laydatecss{display:none;position:absolute;width:1989px}.laydate_body .laydate_box,.laydate_body .laydate_box *{margin:0;padding:0;box-sizing:content-box}.laydate-icon,.laydate-icon-dahong,.laydate-icon-danlan,.laydate-icon-default,.laydate-icon-molv{height:22px;line-height:22px;padding-right:20px;border:1px solid #C6C6C6;background-repeat:no-repeat;background-position:right center;background-color:#fff;outline:0}.laydate-icon-default{background-image:url(../skins/default/icon.png)}.laydate-icon-danlan{border:1px solid #B1D2EC;background-image:url(../skins/danlan/icon.png)}.laydate-icon-dahong{background-image:url(../skins/dahong/icon.png)}.laydate-icon-molv{background-image:url(../skins/molv/icon.png)}.laydate_body .laydate_box{width:240px;font:12px '\5B8B\4F53';z-index:99999999;*overflow:hidden;_margin:0;_position:absolute!important}.laydate_body .laydate_box li{list-style:none}.laydate_body .laydate_box .laydate_void{cursor:text!important}.laydate_body .laydate_box cite,.laydate_body .laydate_box label{position:absolute;width:0;height:0;border-width:5px;border-style:dashed;border-color:transparent;overflow:hidden;cursor:pointer}.laydate_body .laydate_box .laydate_time,.laydate_body .laydate_box .laydate_yms{display:none}.laydate_body .laydate_box .laydate_show{display:block}.laydate_body .laydate_box input{outline:0;font-size:14px;background-color:#fff;color:#333}.laydate_body .laydate_top{position:relative;height:26px;padding:5px;*width:100%;z-index:99}.laydate_body .laydate_ym{position:relative;float:left;height:24px;cursor:pointer}.laydate_body .laydate_ym input{float:left;height:24px;line-height:24px;text-align:center;border:none;cursor:pointer}.laydate_body .laydate_ym .laydate_yms{position:absolute;left:-1px;top:24px;height:181px}.laydate_body .laydate_y{width:121px;margin-right:6px}.laydate_body .laydate_y input{width:64px;margin-right:15px}.laydate_body .laydate_y .laydate_yms{width:121px;text-align:center}.laydate_body .laydate_y .laydate_yms a{position:relative;display:block;height:20px}.laydate_body .laydate_y .laydate_yms ul{height:139px;padding:0;*overflow:hidden}.laydate_body .laydate_y .laydate_yms ul li{float:left;width:60px;height:20px;line-height:20px;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.laydate_body .laydate_m{width:99px}.laydate_body .laydate_m .laydate_yms{width:99px;padding:0}.laydate_body .laydate_m input{width:42px;margin-right:15px}.laydate_body .laydate_m .laydate_yms span{display:block;float:left;width:42px;margin:5px 0 0 5px;line-height:24px;text-align:center;_display:inline}.laydate_body .laydate_choose{display:block;float:left;position:relative;width:20px;height:24px}.laydate_body .laydate_choose cite,.laydate_body .laydate_tab cite{left:50%;top:50%}.laydate_body .laydate_chtop cite{margin:-7px 0 0 -5px;border-bottom-style:solid}.laydate_body .laydate_chdown cite,.laydate_body .laydate_ym label{top:50%;margin:-2px 0 0 -5px;border-top-style:solid}.laydate_body .laydate_chprev cite{margin:-5px 0 0 -7px}.laydate_body .laydate_chnext cite{margin:-5px 0 0 -2px}.laydate_body .laydate_ym label{right:28px}.laydate_body .laydate_table{width:230px;margin:0 5px;border-collapse:collapse;border-spacing:0}.laydate_body .laydate_table td{width:31px;text-align:center;cursor:pointer;font-size:12px}.laydate_body .laydate_table thead th{font-weight:400;font-size:12px;text-align:center}.laydate_body .laydate_bottom{position:relative;height:22px;line-height:20px;padding:5px;font-size:12px}.laydate_body .laydate_bottom #laydate_hms{position:relative;z-index:1;float:left}.laydate_body .laydate_time{position:absolute;left:5px;bottom:26px;width:129px;height:125px;*overflow:hidden}.laydate_body .laydate_time .laydate_hmsno{padding:5px 0 0 5px}.laydate_body .laydate_time .laydate_hmsno span{display:block;float:left;width:24px;height:19px;line-height:19px;text-align:center;cursor:pointer;*margin-bottom:-5px}.laydate_body .laydate_time1{width:228px;height:154px}.laydate_body .laydate_time1 .laydate_hmsno{padding:6px 0 0 8px}.laydate_body .laydate_time1 .laydate_hmsno span{width:21px;height:20px;line-height:20px}.laydate_body .laydate_msg{left:49px;bottom:67px;width:141px;height:auto;overflow:hidden}.laydate_body .laydate_msg p{padding:5px 10px}.laydate_body .laydate_bottom li{float:left;height:20px;line-height:20px;border-right:none;font-weight:900}.laydate_body .laydate_bottom .laydate_sj{width:33px;text-align:center;font-weight:400}.laydate_body .laydate_bottom input{float:left;width:21px;height:20px;line-height:20px;border:none;text-align:center;cursor:pointer;font-size:12px;font-weight:400}.laydate_body .laydate_bottom .laydte_hsmtex{height:20px;line-height:20px;text-align:center}.laydate_body .laydate_bottom .laydte_hsmtex span{position:absolute;width:20px;top:0;right:0;cursor:pointer}.laydate_body .laydate_bottom .laydte_hsmtex span:hover{font-size:14px}.laydate_body .laydate_bottom .laydate_btn{position:absolute;right:5px;top:5px}.laydate_body .laydate_bottom .laydate_btn a{float:left;height:20px;padding:0 6px;_padding:0 5px}.laydate_body .laydate_table td,.laydate_body .laydate_table thead{height:21px!important;line-height:21px!important}.laydate-icon{border:1px solid #C6C6C6;background-image:url(icon.png)}.laydate_body .laydate_bottom #laydate_hms,.laydate_body .laydate_bottom .laydate_btn a,.laydate_body .laydate_box,.laydate_body .laydate_table,.laydate_body .laydate_table td,.laydate_body .laydate_time,.laydate_body .laydate_ym,.laydate_body .laydate_ym .laydate_yms{border:1px solid #ccc}.laydate_body .laydate_bottom .laydte_hsmtex,.laydate_body .laydate_choose,.laydate_body .laydate_table thead,.laydate_body .laydate_y .laydate_yms a{background-color:#F6F6F6}.laydate_body .laydate_box,.laydate_body .laydate_time,.laydate_body .laydate_ym .laydate_yms{box-shadow:2px 2px 5px rgba(0,0,0,.1)}.laydate_body .laydate_box{border-top:none;border-bottom:none;background-color:#fff;color:#333}.laydate_body .laydate_box .laydate_void{color:#ccc!important}.laydate_body .laydate_box .laydate_void:hover{background-color:#fff!important}.laydate_body .laydate_box a,.laydate_body .laydate_box a:hover{text-decoration:none;blr:expression(this.onFocus=this.blur());cursor:pointer;color:#333}.laydate_body .laydate_box a:hover{text-decoration:none;color:#666}.laydate_body .laydate_click{background-color:#eee!important}.laydate_body .laydate_bottom #laydate_hms,.laydate_body .laydate_choose:hover,.laydate_body .laydate_table td,.laydate_body .laydate_time,.laydate_body .laydate_y .laydate_yms a:hover{background-color:#fff}.laydate_body .laydate_top{border-top:1px solid #C6C6C6}.laydate_body .laydate_ym .laydate_yms{border:1px solid #C6C6C6;background-color:#fff}.laydate_body .laydate_y .laydate_yms a{border-bottom:1px solid #C6C6C6}.laydate_body .laydate_y .laydate_yms .laydate_chdown{border-top:1px solid #C6C6C6;border-bottom:none}.laydate_body .laydate_choose{border-left:1px solid #C6C6C6}.laydate_body .laydate_chprev{border-left:none;border-right:1px solid #C6C6C6}.laydate_body .laydate_chtop cite{border-bottom-color:#666}.laydate_body .laydate_chdown cite,.laydate_body .laydate_ym label{border-top-color:#666}.laydate_body .laydate_chprev cite{border-right-style:solid;border-right-color:#666}.laydate_body .laydate_chnext cite{border-left-style:solid;border-left-color:#666}.laydate_body .laydate_table td{border:none}.laydate_body .laydate_table .laydate_nothis{color:#999}.laydate_body .laydate_table thead th{border-bottom:1px solid #ccc}.laydate_body .laydate_bottom,.laydate_body .laydate_bottom .laydte_hsmtex{border-bottom:1px solid #C6C6C6}.laydate_body .laydate_bottom .laydate_sj{border-right:1px solid #C6C6C6;background-color:#F6F6F6}.laydate_body .laydate_bottom input{background-color:#fff}.laydate_body .laydate_bottom .laydate_btn{border-right:1px solid #C6C6C6}.laydate_body .laydate_bottom .laydate_v{position:absolute;left:10px;top:6px;font-family:Courier;z-index:0;color:#999}.laydate_body .laydate_bottom .laydate_btn a{border-right:none;background-color:#F6F6F6}.laydate_body .laydate_bottom .laydate_btn a:hover{color:#000;background-color:#fff}.laydate_body .laydate_m .laydate_yms span:hover,.laydate_body .laydate_table td:hover,.laydate_body .laydate_time .laydate_hmsno span:hover,.laydate_body .laydate_y .laydate_yms ul li:hover{background-color:#F3F3F3}
\ No newline at end of file
diff --git a/build/css/modules/layer/default/icon-ext.png b/build/css/modules/layer/default/icon-ext.png
deleted file mode 100644
index bbbb669bb..000000000
Binary files a/build/css/modules/layer/default/icon-ext.png and /dev/null differ
diff --git a/build/css/modules/layer/default/icon.png b/build/css/modules/layer/default/icon.png
deleted file mode 100644
index 3e17da8b1..000000000
Binary files a/build/css/modules/layer/default/icon.png and /dev/null differ
diff --git a/build/css/modules/layer/default/layer.css b/build/css/modules/layer/default/layer.css
deleted file mode 100644
index 9f2e52321..000000000
--- a/build/css/modules/layer/default/layer.css
+++ /dev/null
@@ -1,2 +0,0 @@
-/** layui-v1.0.9_rls MIT License By http://www.layui.com */
- .layui-layer-imgbar,.layui-layer-imgtit a,.layui-layer-tab .layui-layer-title span,.layui-layer-title{text-overflow:ellipsis;white-space:nowrap}*html{background-image:url(about:blank);background-attachment:fixed}html #layuicss-skinlayercss{display:none;position:absolute;width:1989px}.layui-layer,.layui-layer-shade{position:fixed;_position:absolute;pointer-events:auto}.layui-layer-shade{top:0;left:0;width:100%;height:100%;_height:expression(document.body.offsetHeight+"px")}.layui-layer{-webkit-overflow-scrolling:touch;top:150px;left:0;margin:0;padding:0;background-color:#fff;-webkit-background-clip:content;box-shadow:1px 1px 50px rgba(0,0,0,.3)}.layui-layer-close{position:absolute}.layui-layer-content{position:relative}.layui-layer-border{border:1px solid #B2B2B2;border:1px solid rgba(0,0,0,.1);box-shadow:1px 1px 5px rgba(0,0,0,.2)}.layui-layer-load{background:url(loading-1.gif) center center no-repeat #eee}.layui-layer-ico{background:url(icon.png) no-repeat}.layui-layer-btn a,.layui-layer-dialog .layui-layer-ico,.layui-layer-setwin a{display:inline-block;*display:inline;*zoom:1;vertical-align:top}.layui-layer-move{display:none;position:fixed;*position:absolute;left:0;top:0;width:100%;height:100%;cursor:move;opacity:0;filter:alpha(opacity=0);background-color:#fff;z-index:2147483647}.layui-layer-resize{position:absolute;width:15px;height:15px;right:0;bottom:0;cursor:se-resize}.layui-layer{border-radius:2px;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-duration:.3s;animation-duration:.3s}@-webkit-keyframes layer-bounceIn{0%{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}@keyframes layer-bounceIn{0%{opacity:0;-webkit-transform:scale(.5);-ms-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}.layer-anim{-webkit-animation-name:layer-bounceIn;animation-name:layer-bounceIn}@-webkit-keyframes layer-zoomInDown{0%{opacity:0;-webkit-transform:scale(.1) translateY(-2000px);transform:scale(.1) translateY(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateY(60px);transform:scale(.475) translateY(60px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}@keyframes layer-zoomInDown{0%{opacity:0;-webkit-transform:scale(.1) translateY(-2000px);-ms-transform:scale(.1) translateY(-2000px);transform:scale(.1) translateY(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateY(60px);-ms-transform:scale(.475) translateY(60px);transform:scale(.475) translateY(60px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}.layer-anim-01{-webkit-animation-name:layer-zoomInDown;animation-name:layer-zoomInDown}@-webkit-keyframes layer-fadeInUpBig{0%{opacity:0;-webkit-transform:translateY(2000px);transform:translateY(2000px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes layer-fadeInUpBig{0%{opacity:0;-webkit-transform:translateY(2000px);-ms-transform:translateY(2000px);transform:translateY(2000px)}100%{opacity:1;-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}.layer-anim-02{-webkit-animation-name:layer-fadeInUpBig;animation-name:layer-fadeInUpBig}@-webkit-keyframes layer-zoomInLeft{0%{opacity:0;-webkit-transform:scale(.1) translateX(-2000px);transform:scale(.1) translateX(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateX(48px);transform:scale(.475) translateX(48px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}@keyframes layer-zoomInLeft{0%{opacity:0;-webkit-transform:scale(.1) translateX(-2000px);-ms-transform:scale(.1) translateX(-2000px);transform:scale(.1) translateX(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateX(48px);-ms-transform:scale(.475) translateX(48px);transform:scale(.475) translateX(48px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}.layer-anim-03{-webkit-animation-name:layer-zoomInLeft;animation-name:layer-zoomInLeft}@-webkit-keyframes layer-rollIn{0%{opacity:0;-webkit-transform:translateX(-100%) rotate(-120deg);transform:translateX(-100%) rotate(-120deg)}100%{opacity:1;-webkit-transform:translateX(0) rotate(0);transform:translateX(0) rotate(0)}}@keyframes layer-rollIn{0%{opacity:0;-webkit-transform:translateX(-100%) rotate(-120deg);-ms-transform:translateX(-100%) rotate(-120deg);transform:translateX(-100%) rotate(-120deg)}100%{opacity:1;-webkit-transform:translateX(0) rotate(0);-ms-transform:translateX(0) rotate(0);transform:translateX(0) rotate(0)}}.layer-anim-04{-webkit-animation-name:layer-rollIn;animation-name:layer-rollIn}@keyframes layer-fadeIn{0%{opacity:0}100%{opacity:1}}.layer-anim-05{-webkit-animation-name:layer-fadeIn;animation-name:layer-fadeIn}@-webkit-keyframes layer-shake{0%,100%{-webkit-transform:translateX(0);transform:translateX(0)}10%,30%,50%,70%,90%{-webkit-transform:translateX(-10px);transform:translateX(-10px)}20%,40%,60%,80%{-webkit-transform:translateX(10px);transform:translateX(10px)}}@keyframes layer-shake{0%,100%{-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}10%,30%,50%,70%,90%{-webkit-transform:translateX(-10px);-ms-transform:translateX(-10px);transform:translateX(-10px)}20%,40%,60%,80%{-webkit-transform:translateX(10px);-ms-transform:translateX(10px);transform:translateX(10px)}}.layer-anim-06{-webkit-animation-name:layer-shake;animation-name:layer-shake}@-webkit-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}.layui-layer-title{padding:0 80px 0 20px;height:42px;line-height:42px;border-bottom:1px solid #eee;font-size:14px;color:#333;overflow:hidden;background-color:#F8F8F8;border-radius:2px 2px 0 0}.layui-layer-setwin{position:absolute;right:15px;*right:0;top:15px;font-size:0;line-height:initial}.layui-layer-setwin a{position:relative;width:16px;height:16px;margin-left:10px;font-size:12px;_overflow:hidden}.layui-layer-setwin .layui-layer-min cite{position:absolute;width:14px;height:2px;left:0;top:50%;margin-top:-1px;background-color:#2E2D3C;cursor:pointer;_overflow:hidden}.layui-layer-setwin .layui-layer-min:hover cite{background-color:#2D93CA}.layui-layer-setwin .layui-layer-max{background-position:-32px -40px}.layui-layer-setwin .layui-layer-max:hover{background-position:-16px -40px}.layui-layer-setwin .layui-layer-maxmin{background-position:-65px -40px}.layui-layer-setwin .layui-layer-maxmin:hover{background-position:-49px -40px}.layui-layer-setwin .layui-layer-close1{background-position:1px -40px;cursor:pointer}.layui-layer-setwin .layui-layer-close1:hover{opacity:.7}.layui-layer-setwin .layui-layer-close2{position:absolute;right:-28px;top:-28px;width:30px;height:30px;margin-left:0;background-position:-149px -31px;*right:-18px;_display:none}.layui-layer-setwin .layui-layer-close2:hover{background-position:-180px -31px}.layui-layer-btn{text-align:right;padding:0 10px 12px;pointer-events:auto;user-select:none;-webkit-user-select:none}.layui-layer-btn a{height:28px;line-height:28px;margin:6px 6px 0;padding:0 15px;border:1px solid #dedede;background-color:#f1f1f1;color:#333;border-radius:2px;font-weight:400;cursor:pointer;text-decoration:none}.layui-layer-btn a:hover{opacity:.9;text-decoration:none}.layui-layer-btn a:active{opacity:.8}.layui-layer-btn .layui-layer-btn0{border-color:#4898d5;background-color:#2e8ded;color:#fff}.layui-layer-btn-l{text-align:left}.layui-layer-btn-c{text-align:center}.layui-layer-dialog{min-width:260px}.layui-layer-dialog .layui-layer-content{position:relative;padding:20px;line-height:24px;word-break:break-all;overflow:hidden;font-size:14px;overflow-x:hidden;overflow-y:auto}.layui-layer-dialog .layui-layer-content .layui-layer-ico{position:absolute;top:16px;left:15px;_left:-40px;width:30px;height:30px}.layui-layer-ico1{background-position:-30px 0}.layui-layer-ico2{background-position:-60px 0}.layui-layer-ico3{background-position:-90px 0}.layui-layer-ico4{background-position:-120px 0}.layui-layer-ico5{background-position:-150px 0}.layui-layer-ico6{background-position:-180px 0}.layui-layer-rim{border:6px solid #8D8D8D;border:6px solid rgba(0,0,0,.3);border-radius:5px;box-shadow:none}.layui-layer-msg{min-width:180px;border:1px solid #D3D4D3;box-shadow:none}.layui-layer-hui{min-width:100px;background-color:#000;filter:alpha(opacity=60);background-color:rgba(0,0,0,.6);color:#fff;border:none}.layui-layer-hui .layui-layer-content{padding:12px 25px;text-align:center}.layui-layer-dialog .layui-layer-padding{padding:20px 20px 20px 55px;text-align:left}.layui-layer-page .layui-layer-content{position:relative;overflow:auto}.layui-layer-iframe .layui-layer-btn,.layui-layer-page .layui-layer-btn{padding-top:10px}.layui-layer-nobg{background:0 0}.layui-layer-iframe iframe{display:block;width:100%}.layui-layer-loading{border-radius:100%;background:0 0;box-shadow:none;border:none}.layui-layer-loading .layui-layer-content{width:60px;height:24px;background:url(loading-0.gif) no-repeat}.layui-layer-loading .layui-layer-loading1{width:37px;height:37px;background:url(loading-1.gif) no-repeat}.layui-layer-ico16,.layui-layer-loading .layui-layer-loading2{width:32px;height:32px;background:url(loading-2.gif) no-repeat}.layui-layer-tips{background:0 0;box-shadow:none;border:none}.layui-layer-tips .layui-layer-content{position:relative;line-height:22px;min-width:12px;padding:5px 10px;font-size:12px;_float:left;border-radius:2px;box-shadow:1px 1px 3px rgba(0,0,0,.2);background-color:#000;color:#fff}.layui-layer-tips .layui-layer-close{right:-2px;top:-1px}.layui-layer-tips i.layui-layer-TipsG{position:absolute;width:0;height:0;border-width:8px;border-color:transparent;border-style:dashed;*overflow:hidden}.layui-layer-tips i.layui-layer-TipsB,.layui-layer-tips i.layui-layer-TipsT{left:5px;border-right-style:solid;border-right-color:#000}.layui-layer-tips i.layui-layer-TipsT{bottom:-8px}.layui-layer-tips i.layui-layer-TipsB{top:-8px}.layui-layer-tips i.layui-layer-TipsL,.layui-layer-tips i.layui-layer-TipsR{top:1px;border-bottom-style:solid;border-bottom-color:#000}.layui-layer-tips i.layui-layer-TipsR{left:-8px}.layui-layer-tips i.layui-layer-TipsL{right:-8px}.layui-layer-lan[type=dialog]{min-width:280px}.layui-layer-lan .layui-layer-title{background:#4476A7;color:#fff;border:none}.layui-layer-lan .layui-layer-btn{padding:5px 10px 10px;text-align:right;border-top:1px solid #E9E7E7}.layui-layer-lan .layui-layer-btn a{background:#BBB5B5;border:none}.layui-layer-lan .layui-layer-btn .layui-layer-btn1{background:#C9C5C5}.layui-layer-molv .layui-layer-title{background:#009f95;color:#fff;border:none}.layui-layer-molv .layui-layer-btn a{background:#009f95}.layui-layer-molv .layui-layer-btn .layui-layer-btn1{background:#92B8B1}.layui-layer-iconext{background:url(icon-ext.png) no-repeat}.layui-layer-prompt .layui-layer-input{display:block;width:220px;height:30px;margin:0 auto;line-height:30px;padding:0 5px;border:1px solid #ccc;box-shadow:1px 1px 5px rgba(0,0,0,.1) inset;color:#333}.layui-layer-prompt textarea.layui-layer-input{width:300px;height:100px;line-height:20px}.layui-layer-prompt .layui-layer-content{padding:20px}.layui-layer-prompt .layui-layer-btn{padding-top:0}.layui-layer-tab{box-shadow:1px 1px 50px rgba(0,0,0,.4)}.layui-layer-tab .layui-layer-title{padding-left:0;border-bottom:1px solid #ccc;background-color:#eee;overflow:visible}.layui-layer-tab .layui-layer-title span{position:relative;float:left;min-width:80px;max-width:260px;padding:0 20px;text-align:center;cursor:default;overflow:hidden}.layui-layer-tab .layui-layer-title span.layui-layer-tabnow{height:43px;border-left:1px solid #ccc;border-right:1px solid #ccc;background-color:#fff;z-index:10}.layui-layer-tab .layui-layer-title span:first-child{border-left:none}.layui-layer-tabmain{line-height:24px;clear:both}.layui-layer-tabmain .layui-layer-tabli{display:none}.layui-layer-tabmain .layui-layer-tabli.xubox_tab_layer{display:block}.xubox_tabclose{position:absolute;right:10px;top:5px;cursor:pointer}.layui-layer-photos{-webkit-animation-duration:.8s;animation-duration:.8s}.layui-layer-photos .layui-layer-content{overflow:hidden;text-align:center}.layui-layer-photos .layui-layer-phimg img{position:relative;width:100%;display:inline-block;*display:inline;*zoom:1;vertical-align:top}.layui-layer-imgbar,.layui-layer-imguide{display:none}.layui-layer-imgnext,.layui-layer-imgprev{position:absolute;top:50%;width:27px;_width:44px;height:44px;margin-top:-22px;outline:0;blr:expression(this.onFocus=this.blur())}.layui-layer-imgprev{left:10px;background-position:-5px -5px;_background-position:-70px -5px}.layui-layer-imgprev:hover{background-position:-33px -5px;_background-position:-120px -5px}.layui-layer-imgnext{right:10px;_right:8px;background-position:-5px -50px;_background-position:-70px -50px}.layui-layer-imgnext:hover{background-position:-33px -50px;_background-position:-120px -50px}.layui-layer-imgbar{position:absolute;left:0;bottom:0;width:100%;height:32px;line-height:32px;background-color:rgba(0,0,0,.8);background-color:#000\9;filter:Alpha(opacity=80);color:#fff;overflow:hidden;font-size:0}.layui-layer-imgtit *{display:inline-block;*display:inline;*zoom:1;vertical-align:top;font-size:12px}.layui-layer-imgtit a{max-width:65%;overflow:hidden;color:#fff}.layui-layer-imgtit a:hover{color:#fff;text-decoration:underline}.layui-layer-imgtit em{padding-left:10px;font-style:normal}@-webkit-keyframes layer-bounceOut{100%{opacity:0;-webkit-transform:scale(.7);transform:scale(.7)}30%{-webkit-transform:scale(1.05);transform:scale(1.05)}0%{-webkit-transform:scale(1);transform:scale(1)}}@keyframes layer-bounceOut{100%{opacity:0;-webkit-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}30%{-webkit-transform:scale(1.05);-ms-transform:scale(1.05);transform:scale(1.05)}0%{-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}.layer-anim-close{-webkit-animation-name:layer-bounceOut;animation-name:layer-bounceOut;-webkit-animation-duration:.2s;animation-duration:.2s}@media screen and (max-width:1100px){.layui-layer-iframe{overflow-y:auto;-webkit-overflow-scrolling:touch}}
\ No newline at end of file
diff --git a/build/css/modules/layer/default/loading-0.gif b/build/css/modules/layer/default/loading-0.gif
deleted file mode 100644
index 6f3c9539a..000000000
Binary files a/build/css/modules/layer/default/loading-0.gif and /dev/null differ
diff --git a/build/css/modules/layer/default/loading-1.gif b/build/css/modules/layer/default/loading-1.gif
deleted file mode 100644
index db3a483e4..000000000
Binary files a/build/css/modules/layer/default/loading-1.gif and /dev/null differ
diff --git a/build/css/modules/layer/default/loading-2.gif b/build/css/modules/layer/default/loading-2.gif
deleted file mode 100644
index 5bb90fd6a..000000000
Binary files a/build/css/modules/layer/default/loading-2.gif and /dev/null differ
diff --git a/build/font/iconfont.eot b/build/font/iconfont.eot
deleted file mode 100644
index ad72e8dba..000000000
Binary files a/build/font/iconfont.eot and /dev/null differ
diff --git a/build/font/iconfont.svg b/build/font/iconfont.svg
deleted file mode 100644
index 387cf4bb7..000000000
--- a/build/font/iconfont.svg
+++ /dev/null
@@ -1,390 +0,0 @@
-
-
-
-
-Created by FontForge 20120731 at Fri Mar 10 03:16:47 2017
- By admin
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/build/font/iconfont.ttf b/build/font/iconfont.ttf
deleted file mode 100644
index f79ff7725..000000000
Binary files a/build/font/iconfont.ttf and /dev/null differ
diff --git a/build/font/iconfont.woff b/build/font/iconfont.woff
deleted file mode 100644
index fd2428129..000000000
Binary files a/build/font/iconfont.woff and /dev/null differ
diff --git a/build/images/face/0.gif b/build/images/face/0.gif
deleted file mode 100644
index a63f0d523..000000000
Binary files a/build/images/face/0.gif and /dev/null differ
diff --git a/build/images/face/1.gif b/build/images/face/1.gif
deleted file mode 100644
index b2b78b218..000000000
Binary files a/build/images/face/1.gif and /dev/null differ
diff --git a/build/images/face/10.gif b/build/images/face/10.gif
deleted file mode 100644
index 556c7e326..000000000
Binary files a/build/images/face/10.gif and /dev/null differ
diff --git a/build/images/face/11.gif b/build/images/face/11.gif
deleted file mode 100644
index 2bfc58be8..000000000
Binary files a/build/images/face/11.gif and /dev/null differ
diff --git a/build/images/face/12.gif b/build/images/face/12.gif
deleted file mode 100644
index 1c321c7eb..000000000
Binary files a/build/images/face/12.gif and /dev/null differ
diff --git a/build/images/face/13.gif b/build/images/face/13.gif
deleted file mode 100644
index 300bbc2a0..000000000
Binary files a/build/images/face/13.gif and /dev/null differ
diff --git a/build/images/face/14.gif b/build/images/face/14.gif
deleted file mode 100644
index 43b6d0a43..000000000
Binary files a/build/images/face/14.gif and /dev/null differ
diff --git a/build/images/face/15.gif b/build/images/face/15.gif
deleted file mode 100644
index c9f25fa1d..000000000
Binary files a/build/images/face/15.gif and /dev/null differ
diff --git a/build/images/face/16.gif b/build/images/face/16.gif
deleted file mode 100644
index 34f28e4cd..000000000
Binary files a/build/images/face/16.gif and /dev/null differ
diff --git a/build/images/face/17.gif b/build/images/face/17.gif
deleted file mode 100644
index 39cd03538..000000000
Binary files a/build/images/face/17.gif and /dev/null differ
diff --git a/build/images/face/18.gif b/build/images/face/18.gif
deleted file mode 100644
index 7bce2997f..000000000
Binary files a/build/images/face/18.gif and /dev/null differ
diff --git a/build/images/face/19.gif b/build/images/face/19.gif
deleted file mode 100644
index adac542fd..000000000
Binary files a/build/images/face/19.gif and /dev/null differ
diff --git a/build/images/face/2.gif b/build/images/face/2.gif
deleted file mode 100644
index 7edbb58a8..000000000
Binary files a/build/images/face/2.gif and /dev/null differ
diff --git a/build/images/face/20.gif b/build/images/face/20.gif
deleted file mode 100644
index 50631a6e3..000000000
Binary files a/build/images/face/20.gif and /dev/null differ
diff --git a/build/images/face/21.gif b/build/images/face/21.gif
deleted file mode 100644
index b98421282..000000000
Binary files a/build/images/face/21.gif and /dev/null differ
diff --git a/build/images/face/22.gif b/build/images/face/22.gif
deleted file mode 100644
index 1f0bd8b00..000000000
Binary files a/build/images/face/22.gif and /dev/null differ
diff --git a/build/images/face/23.gif b/build/images/face/23.gif
deleted file mode 100644
index e05e0f97a..000000000
Binary files a/build/images/face/23.gif and /dev/null differ
diff --git a/build/images/face/24.gif b/build/images/face/24.gif
deleted file mode 100644
index f35928a26..000000000
Binary files a/build/images/face/24.gif and /dev/null differ
diff --git a/build/images/face/25.gif b/build/images/face/25.gif
deleted file mode 100644
index 0b4a88322..000000000
Binary files a/build/images/face/25.gif and /dev/null differ
diff --git a/build/images/face/26.gif b/build/images/face/26.gif
deleted file mode 100644
index 45c4fb556..000000000
Binary files a/build/images/face/26.gif and /dev/null differ
diff --git a/build/images/face/27.gif b/build/images/face/27.gif
deleted file mode 100644
index 7a4c0131d..000000000
Binary files a/build/images/face/27.gif and /dev/null differ
diff --git a/build/images/face/28.gif b/build/images/face/28.gif
deleted file mode 100644
index fc5a0cfaf..000000000
Binary files a/build/images/face/28.gif and /dev/null differ
diff --git a/build/images/face/29.gif b/build/images/face/29.gif
deleted file mode 100644
index 5dd7442b1..000000000
Binary files a/build/images/face/29.gif and /dev/null differ
diff --git a/build/images/face/3.gif b/build/images/face/3.gif
deleted file mode 100644
index 86df67b7a..000000000
Binary files a/build/images/face/3.gif and /dev/null differ
diff --git a/build/images/face/30.gif b/build/images/face/30.gif
deleted file mode 100644
index b751f98ab..000000000
Binary files a/build/images/face/30.gif and /dev/null differ
diff --git a/build/images/face/31.gif b/build/images/face/31.gif
deleted file mode 100644
index c9476d796..000000000
Binary files a/build/images/face/31.gif and /dev/null differ
diff --git a/build/images/face/32.gif b/build/images/face/32.gif
deleted file mode 100644
index 9931b0636..000000000
Binary files a/build/images/face/32.gif and /dev/null differ
diff --git a/build/images/face/33.gif b/build/images/face/33.gif
deleted file mode 100644
index 59111a38c..000000000
Binary files a/build/images/face/33.gif and /dev/null differ
diff --git a/build/images/face/34.gif b/build/images/face/34.gif
deleted file mode 100644
index a334548e8..000000000
Binary files a/build/images/face/34.gif and /dev/null differ
diff --git a/build/images/face/35.gif b/build/images/face/35.gif
deleted file mode 100644
index a9322643d..000000000
Binary files a/build/images/face/35.gif and /dev/null differ
diff --git a/build/images/face/36.gif b/build/images/face/36.gif
deleted file mode 100644
index 6de432ae9..000000000
Binary files a/build/images/face/36.gif and /dev/null differ
diff --git a/build/images/face/37.gif b/build/images/face/37.gif
deleted file mode 100644
index d05f2da45..000000000
Binary files a/build/images/face/37.gif and /dev/null differ
diff --git a/build/images/face/38.gif b/build/images/face/38.gif
deleted file mode 100644
index 8b1c88a3e..000000000
Binary files a/build/images/face/38.gif and /dev/null differ
diff --git a/build/images/face/39.gif b/build/images/face/39.gif
deleted file mode 100644
index 38b84a513..000000000
Binary files a/build/images/face/39.gif and /dev/null differ
diff --git a/build/images/face/4.gif b/build/images/face/4.gif
deleted file mode 100644
index d52200c51..000000000
Binary files a/build/images/face/4.gif and /dev/null differ
diff --git a/build/images/face/40.gif b/build/images/face/40.gif
deleted file mode 100644
index ae429912d..000000000
Binary files a/build/images/face/40.gif and /dev/null differ
diff --git a/build/images/face/41.gif b/build/images/face/41.gif
deleted file mode 100644
index b9c715c52..000000000
Binary files a/build/images/face/41.gif and /dev/null differ
diff --git a/build/images/face/42.gif b/build/images/face/42.gif
deleted file mode 100644
index 0eb1434b4..000000000
Binary files a/build/images/face/42.gif and /dev/null differ
diff --git a/build/images/face/43.gif b/build/images/face/43.gif
deleted file mode 100644
index ac0b70085..000000000
Binary files a/build/images/face/43.gif and /dev/null differ
diff --git a/build/images/face/44.gif b/build/images/face/44.gif
deleted file mode 100644
index ad4449769..000000000
Binary files a/build/images/face/44.gif and /dev/null differ
diff --git a/build/images/face/45.gif b/build/images/face/45.gif
deleted file mode 100644
index 6837fcaf2..000000000
Binary files a/build/images/face/45.gif and /dev/null differ
diff --git a/build/images/face/46.gif b/build/images/face/46.gif
deleted file mode 100644
index d62916d40..000000000
Binary files a/build/images/face/46.gif and /dev/null differ
diff --git a/build/images/face/47.gif b/build/images/face/47.gif
deleted file mode 100644
index 58a083611..000000000
Binary files a/build/images/face/47.gif and /dev/null differ
diff --git a/build/images/face/48.gif b/build/images/face/48.gif
deleted file mode 100644
index 7ffd1613b..000000000
Binary files a/build/images/face/48.gif and /dev/null differ
diff --git a/build/images/face/49.gif b/build/images/face/49.gif
deleted file mode 100644
index 959b99296..000000000
Binary files a/build/images/face/49.gif and /dev/null differ
diff --git a/build/images/face/5.gif b/build/images/face/5.gif
deleted file mode 100644
index 4e8b09f15..000000000
Binary files a/build/images/face/5.gif and /dev/null differ
diff --git a/build/images/face/50.gif b/build/images/face/50.gif
deleted file mode 100644
index 6e22e7ff1..000000000
Binary files a/build/images/face/50.gif and /dev/null differ
diff --git a/build/images/face/51.gif b/build/images/face/51.gif
deleted file mode 100644
index ad3f4d3a8..000000000
Binary files a/build/images/face/51.gif and /dev/null differ
diff --git a/build/images/face/52.gif b/build/images/face/52.gif
deleted file mode 100644
index 39f8a2284..000000000
Binary files a/build/images/face/52.gif and /dev/null differ
diff --git a/build/images/face/53.gif b/build/images/face/53.gif
deleted file mode 100644
index a181ee778..000000000
Binary files a/build/images/face/53.gif and /dev/null differ
diff --git a/build/images/face/54.gif b/build/images/face/54.gif
deleted file mode 100644
index e289d929b..000000000
Binary files a/build/images/face/54.gif and /dev/null differ
diff --git a/build/images/face/55.gif b/build/images/face/55.gif
deleted file mode 100644
index 4351083ac..000000000
Binary files a/build/images/face/55.gif and /dev/null differ
diff --git a/build/images/face/56.gif b/build/images/face/56.gif
deleted file mode 100644
index e0eff222b..000000000
Binary files a/build/images/face/56.gif and /dev/null differ
diff --git a/build/images/face/57.gif b/build/images/face/57.gif
deleted file mode 100644
index 0bf130f0d..000000000
Binary files a/build/images/face/57.gif and /dev/null differ
diff --git a/build/images/face/58.gif b/build/images/face/58.gif
deleted file mode 100644
index 0f065087d..000000000
Binary files a/build/images/face/58.gif and /dev/null differ
diff --git a/build/images/face/59.gif b/build/images/face/59.gif
deleted file mode 100644
index 7081e4f02..000000000
Binary files a/build/images/face/59.gif and /dev/null differ
diff --git a/build/images/face/6.gif b/build/images/face/6.gif
deleted file mode 100644
index f7715bf52..000000000
Binary files a/build/images/face/6.gif and /dev/null differ
diff --git a/build/images/face/60.gif b/build/images/face/60.gif
deleted file mode 100644
index 6e15f89d7..000000000
Binary files a/build/images/face/60.gif and /dev/null differ
diff --git a/build/images/face/61.gif b/build/images/face/61.gif
deleted file mode 100644
index f092d7e35..000000000
Binary files a/build/images/face/61.gif and /dev/null differ
diff --git a/build/images/face/62.gif b/build/images/face/62.gif
deleted file mode 100644
index 7fe49840b..000000000
Binary files a/build/images/face/62.gif and /dev/null differ
diff --git a/build/images/face/63.gif b/build/images/face/63.gif
deleted file mode 100644
index cf8e23e5b..000000000
Binary files a/build/images/face/63.gif and /dev/null differ
diff --git a/build/images/face/64.gif b/build/images/face/64.gif
deleted file mode 100644
index a7797198a..000000000
Binary files a/build/images/face/64.gif and /dev/null differ
diff --git a/build/images/face/65.gif b/build/images/face/65.gif
deleted file mode 100644
index 7bb98f2d8..000000000
Binary files a/build/images/face/65.gif and /dev/null differ
diff --git a/build/images/face/66.gif b/build/images/face/66.gif
deleted file mode 100644
index bb6d07750..000000000
Binary files a/build/images/face/66.gif and /dev/null differ
diff --git a/build/images/face/67.gif b/build/images/face/67.gif
deleted file mode 100644
index 6e33f7c4f..000000000
Binary files a/build/images/face/67.gif and /dev/null differ
diff --git a/build/images/face/68.gif b/build/images/face/68.gif
deleted file mode 100644
index 1a6c400d2..000000000
Binary files a/build/images/face/68.gif and /dev/null differ
diff --git a/build/images/face/69.gif b/build/images/face/69.gif
deleted file mode 100644
index a02f0b223..000000000
Binary files a/build/images/face/69.gif and /dev/null differ
diff --git a/build/images/face/7.gif b/build/images/face/7.gif
deleted file mode 100644
index e6d4db805..000000000
Binary files a/build/images/face/7.gif and /dev/null differ
diff --git a/build/images/face/70.gif b/build/images/face/70.gif
deleted file mode 100644
index 416c5c14a..000000000
Binary files a/build/images/face/70.gif and /dev/null differ
diff --git a/build/images/face/71.gif b/build/images/face/71.gif
deleted file mode 100644
index c17d60cbd..000000000
Binary files a/build/images/face/71.gif and /dev/null differ
diff --git a/build/images/face/8.gif b/build/images/face/8.gif
deleted file mode 100644
index 66f967b48..000000000
Binary files a/build/images/face/8.gif and /dev/null differ
diff --git a/build/images/face/9.gif b/build/images/face/9.gif
deleted file mode 100644
index 60447400d..000000000
Binary files a/build/images/face/9.gif and /dev/null differ
diff --git a/build/lay/dest/layui.all.js b/build/lay/dest/layui.all.js
deleted file mode 100644
index 8c64407b7..000000000
--- a/build/lay/dest/layui.all.js
+++ /dev/null
@@ -1,5 +0,0 @@
-/** layui-v1.0.9_rls MIT License By http://www.layui.com */
- ;!function(e){"use strict";var t=function(){this.v="1.0.9_rls"};t.fn=t.prototype;var n=document,o=t.fn.cache={},i=function(){var e=n.scripts,t=e[e.length-1].src;return t.substring(0,t.lastIndexOf("/")+1)}(),r=function(t){e.console&&console.error&&console.error("Layui hint: "+t)},a="undefined"!=typeof opera&&"[object Opera]"===opera.toString(),l={layer:"modules/layer",laydate:"modules/laydate",laypage:"modules/laypage",laytpl:"modules/laytpl",layim:"modules/layim",layedit:"modules/layedit",form:"modules/form",upload:"modules/upload",tree:"modules/tree",table:"modules/table",element:"modules/element",util:"modules/util",flow:"modules/flow",carousel:"modules/carousel",code:"modules/code",jquery:"modules/jquery",mobile:"modules/mobile","layui.all":"dest/layui.all"};o.modules={},o.status={},o.timeout=10,o.event={},t.fn.define=function(e,t){var n=this,i="function"==typeof e,r=function(){return"function"==typeof t&&t(function(e,t){layui[e]=t,o.status[e]=!0}),this};return i&&(t=e,e=[]),layui["layui.all"]||!layui["layui.all"]&&layui["layui.mobile"]?r.call(n):(n.use(e,r),n)},t.fn.use=function(e,t,u){function s(e,t){var n="PLaySTATION 3"===navigator.platform?/^complete$/:/^(complete|loaded)$/;("load"===e.type||n.test((e.currentTarget||e.srcElement).readyState))&&(o.modules[m]=t,y.removeChild(v),function i(){return++p>1e3*o.timeout/4?r(m+" is not a valid module"):void(o.status[m]?c():setTimeout(i,4))}())}function c(){u.push(layui[m]),e.length>1?f.use(e.slice(1),t,u):"function"==typeof t&&t.apply(layui,u)}var f=this,d=o.dir=o.dir?o.dir:i,y=n.getElementsByTagName("head")[0];e="string"==typeof e?[e]:e,window.jQuery&&jQuery.fn.on&&(f.each(e,function(t,n){"jquery"===n&&e.splice(t,1)}),layui.jquery=jQuery);var m=e[0],p=0;if(u=u||[],o.host=o.host||(d.match(/\/\/([\s\S]+?)\//)||["//"+location.host+"/"])[0],0===e.length||layui["layui.all"]&&l[m]||!layui["layui.all"]&&layui["layui.mobile"]&&l[m])return c(),f;var v=n.createElement("script"),h=(l[m]?d+"lay/":o.base||"")+(f.modules[m]||m)+".js";return v.async=!0,v.charset="utf-8",v.src=h+function(){var e=o.version===!0?o.v||(new Date).getTime():o.version||"";return e?"?v="+e:""}(),o.modules[m]?!function g(){return++p>1e3*o.timeout/4?r(m+" is not a valid module"):void("string"==typeof o.modules[m]&&o.status[m]?c():setTimeout(g,4))}():(y.appendChild(v),!v.attachEvent||v.attachEvent.toString&&v.attachEvent.toString().indexOf("[native code")<0||a?v.addEventListener("load",function(e){s(e,h)},!1):v.attachEvent("onreadystatechange",function(e){s(e,h)})),o.modules[m]=h,f},t.fn.getStyle=function(t,n){var o=t.currentStyle?t.currentStyle:e.getComputedStyle(t,null);return o[o.getPropertyValue?"getPropertyValue":"getAttribute"](n)},t.fn.link=function(e,t,i){var a=this,l=n.createElement("link"),u=n.getElementsByTagName("head")[0];"string"==typeof t&&(i=t);var s=(i||e).replace(/\.|\//g,""),c=l.id="layuicss-"+s,f=0;return l.rel="stylesheet",l.href=e+(o.debug?"?v="+(new Date).getTime():""),l.media="all",n.getElementById(c)||u.appendChild(l),"function"!=typeof t?a:(function d(){return++f>1e3*o.timeout/100?r(e+" timeout"):void(1989===parseInt(a.getStyle(n.getElementById(c),"width"))?function(){t()}():setTimeout(d,100))}(),a)},t.fn.addcss=function(e,t,n){return layui.link(o.dir+"css/"+e,t,n)},t.fn.img=function(e,t,n){var o=new Image;return o.src=e,o.complete?t(o):(o.onload=function(){o.onload=null,t(o)},void(o.onerror=function(e){o.onerror=null,n(e)}))},t.fn.config=function(e){e=e||{};for(var t in e)o[t]=e[t];return this},t.fn.modules=function(){var e={};for(var t in l)e[t]=l[t];return e}(),t.fn.extend=function(e){var t=this;e=e||{};for(var n in e)t[n]||t.modules[n]?r("模块名 "+n+" 已被占用"):t.modules[n]=e[n];return t},t.fn.router=function(e){var t=this,e=e||location.hash,n={path:[],search:{},hash:(e.match(/[^#](#.*$)/)||[])[1]||""};return/^#\//.test(e)?(e=e.replace(/^#\//,"").replace(/([^#])(#.*$)/,"$1").split("/")||[],t.each(e,function(e,t){/^\w+=/.test(t)?function(){t=t.split("="),n.search[t[0]]=t[1]}():n.path.push(t)}),n):n},t.fn.data=function(t,n){if(t=t||"layui",e.JSON&&e.JSON.parse){if(null===n)return delete localStorage[t];n="object"==typeof n?n:{key:n};try{var o=JSON.parse(localStorage[t])}catch(i){var o={}}return n.value&&(o[n.key]=n.value),n.remove&&delete o[n.key],localStorage[t]=JSON.stringify(o),n.key?o[n.key]:o}},t.fn.device=function(t){var n=navigator.userAgent.toLowerCase(),o=function(e){var t=new RegExp(e+"/([^\\s\\_\\-]+)");return e=(n.match(t)||[])[1],e||!1},i={os:function(){return/windows/.test(n)?"windows":/linux/.test(n)?"linux":/mac/.test(n)?"mac":/iphone|ipod|ipad|ios/.test(n)?"ios":void 0}(),ie:function(){return!!(e.ActiveXObject||"ActiveXObject"in e)&&((n.match(/msie\s(\d+)/)||[])[1]||"11")}(),weixin:o("micromessenger")};return t&&!i[t]&&(i[t]=o(t)),i.android=/android/.test(n),i.ios="ios"===i.os,i},t.fn.hint=function(){return{error:r}},t.fn.each=function(e,t){var n,o=this;if("function"!=typeof t)return o;if(e=e||[],e.constructor===Object){for(n in e)if(t.call(e[n],n,e[n]))break}else for(n=0;n /g,">").replace(/'/g,"'").replace(/"/g,""")},error:function(e,r){var n="Laytpl Error:";return"object"==typeof console&&console.error(n+e+"\n"+(r||"")),n+e}},c=n.exp,t=function(e){this.tpl=e};t.pt=t.prototype,window.errors=0,t.pt.parse=function(e,t){var o=this,p=e,a=c("^"+r.open+"#",""),l=c(r.close+"$","");e=e.replace(/\s+|\r|\t|\n/g," ").replace(c(r.open+"#"),r.open+"# ").replace(c(r.close+"}"),"} "+r.close).replace(/\\/g,"\\\\").replace(/(?="|')/g,"\\").replace(n.query(),function(e){return e=e.replace(a,"").replace(l,""),'";'+e.replace(/\\/g,"")+';view+="'}).replace(n.query(1),function(e){var n='"+(';return e.replace(/\s/g,"")===r.open+r.close?"":(e=e.replace(c(r.open+"|"+r.close),""),/^=/.test(e)&&(e=e.replace(/^=/,""),n='"+_escape_('),n+e.replace(/\\/g,"")+')+"')}),e='"use strict";var view = "'+e+'";return view;';try{return o.cache=e=new Function("d, _escape_",e),e(t,n.escape)}catch(u){return delete o.cache,n.error(u,p)}},t.pt.render=function(e,r){var c,t=this;return e?(c=t.cache?t.cache(e,n.escape):t.parse(t.tpl,e),r?void r(c):c):n.error("no data")};var o=function(e){return"string"!=typeof e?n.error("Template not found"):new t(e)};o.config=function(e){e=e||{};for(var n in e)r[n]=e[n]},o.v="1.2.0",e("laytpl",o)});layui.define(function(a){"use strict";function t(a){new p(a)}var e=document,r="getElementById",n="getElementsByTagName",s=0,p=function(a){var t=this,e=t.config=a||{};e.item=s++,t.render(!0)};p.on=function(a,t,e){return a.attachEvent?a.attachEvent("on"+t,function(){e.call(a,window.even)}):a.addEventListener(t,e,!1),p},p.prototype.type=function(){var a=this.config;if("object"==typeof a.cont)return void 0===a.cont.length?2:3},p.prototype.view=function(){var a=this,t=a.config,e=[],r={};if(t.pages=0|t.pages,t.curr=0|t.curr||1,t.groups="groups"in t?0|t.groups:5,t.first="first"in t?t.first:"首页",t.last="last"in t?t.last:"末页",t.prev="prev"in t?t.prev:"上一页",t.next="next"in t?t.next:"下一页",t.pages<=1)return"";for(t.groups>t.pages&&(t.groups=t.pages),r.index=Math.ceil((t.curr+(t.groups>1&&t.groups!==t.pages?1:0))/(0===t.groups?1:t.groups)),t.curr>1&&t.prev&&e.push(''+t.prev+" "),r.index>1&&t.first&&0!==t.groups&&e.push(''+t.first+" … "),r.poor=Math.floor((t.groups-1)/2),r.start=r.index>1?t.curr-r.poor:1,r.end=r.index>1?function(){var a=t.curr+(t.groups-r.poor-1);return a>t.pages?t.pages:a}():t.groups,r.end-r.start"+r.start+" "):e.push(''+r.start+" ");return t.pages>t.groups&&r.end…'+t.last+" "),r.flow=!t.prev&&0===t.groups,(t.curr!==t.pages&&t.next||r.flow)&&e.push(function(){return r.flow&&t.curr===t.pages?''+t.next+" ":''+t.next+" "}()),''+e.join("")+function(){return t.skip?'到第 页 确定 ':""}()+"
"},p.prototype.jump=function(a){if(a){for(var t=this,e=t.config,r=a.children,s=a[n]("button")[0],i=a[n]("input")[0],u=0,o=r.length;un.maxs[0]?s=["y",1]:e>=n.mins[0]&&e<=n.maxs[0]&&(e==n.mins[0]&&(tn.maxs[1]?s=["m",1]:t==n.maxs[1]&&a>n.maxs[2]&&(s=["d",1]))),s},n.timeVoid=function(e,t){if(n.ymd[1]+1==n.mins[1]&&n.ymd[2]==n.mins[2]){if(0===t&&en.maxs[3])return 1;if(1===t&&e>n.maxs[4])return 1;if(2===t&&e>n.maxs[5])return 1}if(e>(t?59:23))return 1},n.check=function(){var e=n.options.format.replace(/YYYY|MM|DD|hh|mm|ss/g,"\\d+\\").replace(/\\$/g,""),t=new RegExp(e),a=n.elem[d.elemv],s=a.match(/\d+/g)||[],i=n.checkVoid(s[0],s[1],s[2]);if(""!==a.replace(/\s/g,"")){if(!t.test(a))return n.elem[d.elemv]="",n.msg("日期不符合格式,请重新选择。"),1;if(i[0])return n.elem[d.elemv]="",n.msg("日期不在有效期内,请重新选择。"),1;i.value=n.elem[d.elemv].match(t).join(),s=i.value.match(/\d+/g),s[1]<1?(s[1]=1,i.auto=1):s[1]>12?(s[1]=12,i.auto=1):s[1].length<2&&(i.auto=1),s[2]<1?(s[2]=1,i.auto=1):s[2]>n.months[(0|s[1])-1]?(s[2]=31,i.auto=1):s[2].length<2&&(i.auto=1),s.length>3&&(n.timeVoid(s[3],0)&&(i.auto=1),n.timeVoid(s[4],1)&&(i.auto=1),n.timeVoid(s[5],2)&&(i.auto=1)),i.auto?n.creation([s[0],0|s[1],0|s[2]],1):i.value!==n.elem[d.elemv]&&(n.elem[d.elemv]=i.value)}},n.months=[31,null,31,30,31,30,31,31,30,31,30,31],n.viewDate=function(e,t,a){var s=(n.query,{}),i=new Date;e<(0|n.mins[0])&&(e=0|n.mins[0]),e>(0|n.maxs[0])&&(e=0|n.maxs[0]),i.setFullYear(e,t,a),s.ymd=[i.getFullYear(),i.getMonth(),i.getDate()],n.months[1]=n.isleap(s.ymd[0])?29:28,i.setFullYear(s.ymd[0],s.ymd[1],1),s.FDay=i.getDay(),s.PDay=n.months[0===t?11:t-1]-s.FDay+1,s.NDay=1,n.each(d.tds,function(e,t){var a,i=s.ymd[0],o=s.ymd[1]+1;t.className="",e=s.FDay&&e'+e+"年":''+(e-7+t)+"年 "}),t("#laydate_ys").innerHTML=a,n.each(t("#laydate_ys li"),function(e,t){"y"===n.checkVoid(t.getAttribute("y"))[0]?n.addClass(t,d[1]):n.on(t,"click",function(e){n.stopmp(e).reshow(),n.viewDate(0|this.getAttribute("y"),n.ymd[1],n.ymd[2])})})},n.initDate=function(){var e=(n.query,new Date),t=n.elem[d.elemv].match(/\d+/g)||[];t.length<3&&(t=n.options.start.match(/\d+/g)||[],t.length<3&&(t=[e.getFullYear(),e.getMonth()+1,e.getDate()])),n.inymd=t,n.viewDate(t[0],t[1]-1,t[2])},n.iswrite=function(){var e=n.query,t={time:e("#laydate_hms")};n.shde(t.time,!n.options.istime),n.shde(d.oclear,!("isclear"in n.options?n.options.isclear:1)),n.shde(d.otoday,!("istoday"in n.options?n.options.istoday:1)),n.shde(d.ok,!("issure"in n.options?n.options.issure:1))},n.orien=function(e,t){var a,s=n.elem.getBoundingClientRect();e.style.left=s.left+(t?0:n.scroll(1))+"px",a=s.bottom+e.offsetHeight/1.5<=n.winarea()?s.bottom-1:s.top>e.offsetHeight/1.5?s.top-e.offsetHeight+1:n.winarea()-e.offsetHeight,e.style.top=Math.max(a+(t?0:n.scroll()),1)+"px"},n.follow=function(e){n.options.fixed?(e.style.position="fixed",n.orien(e,1)):(e.style.position="absolute",n.orien(e))},n.viewtb=function(){var e,t=[],a=["日","一","二","三","四","五","六"],o={},d=s[i]("table"),r=s[i]("thead");return r.appendChild(s[i]("tr")),o.creath=function(e){var t=s[i]("th");t.innerHTML=a[e],r[l]("tr")[0].appendChild(t),t=null},n.each(new Array(6),function(a){t.push([]),e=d.insertRow(0),n.each(new Array(7),function(n){t[a][n]=0,0===a&&o.creath(n),e.insertCell(n)})}),d.insertBefore(r,d.children[0]),d.id=d.className="laydate_table",e=t=null,d.outerHTML.toLowerCase()}(),n.view=function(e,t){var o,l=n.query,r={};t=t||e,n.elem=e,n.options=t,n.options.format||(n.options.format=a.format),n.options.start=n.options.start||"",n.mm=r.mm=[n.options.min||a.min,n.options.max||a.max],n.mins=r.mm[0].match(/\d+/g),n.maxs=r.mm[1].match(/\d+/g),n.box?n.shde(n.box):(o=s[i]("div"),o.id=d[0],o.className=d[0],o.style.cssText="position: absolute;",o.setAttribute("name","laydate-v"+laydate.v),o.innerHTML=r.html='"+n.viewtb+'",s.body.appendChild(o),n.box=l("#"+d[0]),n.events(),o=null),n.follow(n.box),t.zIndex?n.box.style.zIndex=t.zIndex:n.removeCssAttr(n.box,"z-index"),n.stopMosup("click",n.box),n.initDate(),n.iswrite(),n.check()},n.reshow=function(){return n.each(n.query("#"+d[0]+" .laydate_show"),function(e,t){n.removeClass(t,"laydate_show")}),this},n.close=function(){n.reshow(),n.shde(n.query("#"+d[0]),1),n.elem=null},n.parse=function(e,t,s){return e=e.concat(t),s=s||(n.options?n.options.format:a.format),s.replace(/YYYY|MM|DD|hh|mm|ss/g,function(t,a){return e.index=0|++e.index,n.digit(e[e.index])})},n.creation=function(e,t){var a=(n.query,n.hmsin),s=n.parse(e,[a[0].value,a[1].value,a[2].value]);n.elem[d.elemv]=s,t||(n.close(),"function"==typeof n.options.choose&&n.options.choose(s))},n.events=function(){var e=n.query,a={box:"#"+d[0]};n.addClass(s.body,"laydate_body"),d.tds=e("#laydate_table td"),d.mms=e("#laydate_ms span"),d.year=e("#laydate_y"),d.month=e("#laydate_m"),n.each(e(a.box+" .laydate_ym"),function(e,t){n.on(t,"click",function(t){n.stopmp(t).reshow(),n.addClass(this[l]("div")[0],"laydate_show"),e||(a.YY=parseInt(d.year.value),n.viewYears(a.YY))})}),n.on(e(a.box),"click",function(){n.reshow()}),a.tabYear=function(e){0===e?n.ymd[0]--:1===e?n.ymd[0]++:2===e?a.YY-=14:a.YY+=14,e<2?(n.viewDate(n.ymd[0],n.ymd[1],n.ymd[2]),n.reshow()):n.viewYears(a.YY)},n.each(e("#laydate_YY .laydate_tab"),function(e,t){n.on(t,"click",function(t){n.stopmp(t),a.tabYear(e)})}),a.tabMonth=function(e){e?(n.ymd[1]++,12===n.ymd[1]&&(n.ymd[0]++,n.ymd[1]=0)):(n.ymd[1]--,n.ymd[1]===-1&&(n.ymd[0]--,n.ymd[1]=11)),n.viewDate(n.ymd[0],n.ymd[1],n.ymd[2])},n.each(e("#laydate_MM .laydate_tab"),function(e,t){n.on(t,"click",function(t){n.stopmp(t).reshow(),a.tabMonth(e)})}),n.each(e("#laydate_ms span"),function(e,t){n.on(t,"click",function(e){n.stopmp(e).reshow(),n.hasClass(this,d[1])||n.viewDate(n.ymd[0],0|this.getAttribute("m"),n.ymd[2])})}),n.each(e("#laydate_table td"),function(e,t){n.on(t,"click",function(e){n.hasClass(this,d[1])||(n.stopmp(e),n.creation([0|this.getAttribute("y"),0|this.getAttribute("m"),0|this.getAttribute("d")]))})}),d.oclear=e("#laydate_clear"),n.on(d.oclear,"click",function(){n.elem[d.elemv]="",n.close()}),d.otoday=e("#laydate_today"),n.on(d.otoday,"click",function(){var e=new Date;n.creation([e.getFullYear(),e.getMonth()+1,e.getDate()])}),d.ok=e("#laydate_ok"),n.on(d.ok,"click",function(){n.valid&&n.creation([n.ymd[0],n.ymd[1]+1,n.ymd[2]])}),a.times=e("#laydate_time"),n.hmsin=a.hmsin=e("#laydate_hms input"),a.hmss=["小时","分钟","秒数"],a.hmsarr=[],n.msg=function(t,s){var i=''+(s||"提示")+"×
";"string"==typeof t?(i+=""+t+"
",n.shde(e("#"+d[0])),n.removeClass(a.times,"laydate_time1").addClass(a.times,"laydate_msg")):(a.hmsarr[t]?i=a.hmsarr[t]:(i+='',n.each(new Array(0===t?24:60),function(e){i+=""+e+" "}),i+="
",a.hmsarr[t]=i),n.removeClass(a.times,"laydate_msg"),n[0===t?"removeClass":"addClass"](a.times,"laydate_time1")),n.addClass(a.times,"laydate_show"),a.times.innerHTML=i},a.hmson=function(t,a){var s=e("#laydate_hmsno span"),i=n.valid?null:1;n.each(s,function(e,s){i?n.addClass(s,d[1]):n.timeVoid(e,a)?n.addClass(s,d[1]):n.on(s,"click",function(e){n.hasClass(this,d[1])||(t.value=n.digit(0|this.innerHTML))})}),n.addClass(s[0|t.value],"laydate_click")},n.each(a.hmsin,function(e,t){n.on(t,"click",function(t){n.stopmp(t).reshow(),n.msg(e,a.hmss[e]),a.hmson(this,e)})}),n.on(s,"mouseup",function(){var t=e("#"+d[0]);t&&"none"!==t.style.display&&(n.check()||n.close())}).on(s,"keydown",function(e){e=e||t.event;var a=e.keyCode;13===a&&n.elem&&n.creation([n.ymd[0],n.ymd[1]+1,n.ymd[2]])})},laydate.reset=function(){n.box&&n.elem&&n.follow(n.box)},laydate.now=function(e,t){var a=new Date(0|e?function(e){return e<864e5?+new Date+864e5*e:e}(parseInt(e)):+new Date);return n.parse([a.getFullYear(),a.getMonth()+1,a.getDate()],[a.getHours(),a.getMinutes(),a.getSeconds()],t)},layui.addcss("modules/laydate/laydate.css",function(){},"laydatecss"),e("laydate",laydate)});!function(e,t){"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(e,t){function n(e){var t=!!e&&"length"in e&&e.length,n=pe.type(e);return"function"!==n&&!pe.isWindow(e)&&("array"===n||0===t||"number"==typeof t&&t>0&&t-1 in e)}function r(e,t,n){if(pe.isFunction(t))return pe.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return pe.grep(e,function(e){return e===t!==n});if("string"==typeof t){if(Ce.test(t))return pe.filter(t,e,n);t=pe.filter(t,e)}return pe.grep(e,function(e){return pe.inArray(e,t)>-1!==n})}function i(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}function o(e){var t={};return pe.each(e.match(De)||[],function(e,n){t[n]=!0}),t}function a(){re.addEventListener?(re.removeEventListener("DOMContentLoaded",s),e.removeEventListener("load",s)):(re.detachEvent("onreadystatechange",s),e.detachEvent("onload",s))}function s(){(re.addEventListener||"load"===e.event.type||"complete"===re.readyState)&&(a(),pe.ready())}function u(e,t,n){if(void 0===n&&1===e.nodeType){var r="data-"+t.replace(_e,"-$1").toLowerCase();if(n=e.getAttribute(r),"string"==typeof n){try{n="true"===n||"false"!==n&&("null"===n?null:+n+""===n?+n:qe.test(n)?pe.parseJSON(n):n)}catch(i){}pe.data(e,t,n)}else n=void 0}return n}function l(e){var t;for(t in e)if(("data"!==t||!pe.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}function c(e,t,n,r){if(He(e)){var i,o,a=pe.expando,s=e.nodeType,u=s?pe.cache:e,l=s?e[a]:e[a]&&a;if(l&&u[l]&&(r||u[l].data)||void 0!==n||"string"!=typeof t)return l||(l=s?e[a]=ne.pop()||pe.guid++:a),u[l]||(u[l]=s?{}:{toJSON:pe.noop}),"object"!=typeof t&&"function"!=typeof t||(r?u[l]=pe.extend(u[l],t):u[l].data=pe.extend(u[l].data,t)),o=u[l],r||(o.data||(o.data={}),o=o.data),void 0!==n&&(o[pe.camelCase(t)]=n),"string"==typeof t?(i=o[t],null==i&&(i=o[pe.camelCase(t)])):i=o,i}}function f(e,t,n){if(He(e)){var r,i,o=e.nodeType,a=o?pe.cache:e,s=o?e[pe.expando]:pe.expando;if(a[s]){if(t&&(r=n?a[s]:a[s].data)){pe.isArray(t)?t=t.concat(pe.map(t,pe.camelCase)):t in r?t=[t]:(t=pe.camelCase(t),t=t in r?[t]:t.split(" ")),i=t.length;for(;i--;)delete r[t[i]];if(n?!l(r):!pe.isEmptyObject(r))return}(n||(delete a[s].data,l(a[s])))&&(o?pe.cleanData([e],!0):fe.deleteExpando||a!=a.window?delete a[s]:a[s]=void 0)}}}function d(e,t,n,r){var i,o=1,a=20,s=r?function(){return r.cur()}:function(){return pe.css(e,t,"")},u=s(),l=n&&n[3]||(pe.cssNumber[t]?"":"px"),c=(pe.cssNumber[t]||"px"!==l&&+u)&&Me.exec(pe.css(e,t));if(c&&c[3]!==l){l=l||c[3],n=n||[],c=+u||1;do o=o||".5",c/=o,pe.style(e,t,c+l);while(o!==(o=s()/u)&&1!==o&&--a)}return n&&(c=+c||+u||0,i=n[1]?c+(n[1]+1)*n[2]:+n[2],r&&(r.unit=l,r.start=c,r.end=i)),i}function p(e){var t=ze.split("|"),n=e.createDocumentFragment();if(n.createElement)for(;t.length;)n.createElement(t.pop());return n}function h(e,t){var n,r,i=0,o="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):void 0;if(!o)for(o=[],n=e.childNodes||e;null!=(r=n[i]);i++)!t||pe.nodeName(r,t)?o.push(r):pe.merge(o,h(r,t));return void 0===t||t&&pe.nodeName(e,t)?pe.merge([e],o):o}function g(e,t){for(var n,r=0;null!=(n=e[r]);r++)pe._data(n,"globalEval",!t||pe._data(t[r],"globalEval"))}function m(e){Be.test(e.type)&&(e.defaultChecked=e.checked)}function y(e,t,n,r,i){for(var o,a,s,u,l,c,f,d=e.length,y=p(t),v=[],x=0;x"!==f[1]||Ve.test(a)?0:u:u.firstChild,o=a&&a.childNodes.length;o--;)pe.nodeName(c=a.childNodes[o],"tbody")&&!c.childNodes.length&&a.removeChild(c);for(pe.merge(v,u.childNodes),u.textContent="";u.firstChild;)u.removeChild(u.firstChild);u=y.lastChild}else v.push(t.createTextNode(a));for(u&&y.removeChild(u),fe.appendChecked||pe.grep(h(v,"input"),m),x=0;a=v[x++];)if(r&&pe.inArray(a,r)>-1)i&&i.push(a);else if(s=pe.contains(a.ownerDocument,a),u=h(y.appendChild(a),"script"),s&&g(u),n)for(o=0;a=u[o++];)Ie.test(a.type||"")&&n.push(a);return u=null,y}function v(){return!0}function x(){return!1}function b(){try{return re.activeElement}catch(e){}}function w(e,t,n,r,i,o){var a,s;if("object"==typeof t){"string"!=typeof n&&(r=r||n,n=void 0);for(s in t)w(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),i===!1)i=x;else if(!i)return e;return 1===o&&(a=i,i=function(e){return pe().off(e),a.apply(this,arguments)},i.guid=a.guid||(a.guid=pe.guid++)),e.each(function(){pe.event.add(this,t,i,r,n)})}function T(e,t){return pe.nodeName(e,"table")&&pe.nodeName(11!==t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function C(e){return e.type=(null!==pe.find.attr(e,"type"))+"/"+e.type,e}function E(e){var t=it.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function N(e,t){if(1===t.nodeType&&pe.hasData(e)){var n,r,i,o=pe._data(e),a=pe._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;r1&&"string"==typeof p&&!fe.checkClone&&rt.test(p))return e.each(function(i){var o=e.eq(i);g&&(t[0]=p.call(this,i,o.html())),S(o,t,n,r)});if(f&&(l=y(t,e[0].ownerDocument,!1,e,r),i=l.firstChild,1===l.childNodes.length&&(l=i),i||r)){for(s=pe.map(h(l,"script"),C),a=s.length;c ")).appendTo(t.documentElement),t=(ut[0].contentWindow||ut[0].contentDocument).document,t.write(),t.close(),n=D(e,t),ut.detach()),lt[e]=n),n}function L(e,t){return{get:function(){return e()?void delete this.get:(this.get=t).apply(this,arguments)}}}function H(e){if(e in Et)return e;for(var t=e.charAt(0).toUpperCase()+e.slice(1),n=Ct.length;n--;)if(e=Ct[n]+t,e in Et)return e}function q(e,t){for(var n,r,i,o=[],a=0,s=e.length;a=0&&n=0},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},isPlainObject:function(e){var t;if(!e||"object"!==pe.type(e)||e.nodeType||pe.isWindow(e))return!1;try{if(e.constructor&&!ce.call(e,"constructor")&&!ce.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(n){return!1}if(!fe.ownFirst)for(t in e)return ce.call(e,t);for(t in e);return void 0===t||ce.call(e,t)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?ue[le.call(e)]||"object":typeof e},globalEval:function(t){t&&pe.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(ge,"ms-").replace(me,ye)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t){var r,i=0;if(n(e))for(r=e.length;iT.cacheLength&&delete e[t.shift()],e[n+" "]=r}var t=[];return e}function r(e){return e[P]=!0,e}function i(e){var t=H.createElement("div");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function o(e,t){for(var n=e.split("|"),r=n.length;r--;)T.attrHandle[n[r]]=t}function a(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||V)-(~e.sourceIndex||V);if(r)return r;if(n)for(;n=n.nextSibling;)if(n===t)return-1;return e?1:-1}function s(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function u(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function l(e){return r(function(t){return t=+t,r(function(n,r){for(var i,o=e([],n.length,t),a=o.length;a--;)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}function c(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}function f(){}function d(e){for(var t=0,n=e.length,r="";t1?function(t,n,r){for(var i=e.length;i--;)if(!e[i](t,n,r))return!1;return!0}:e[0]}function g(e,n,r){for(var i=0,o=n.length;i-1&&(r[l]=!(a[l]=f))}}else x=m(x===a?x.splice(h,x.length):x),o?o(null,a,x,u):Q.apply(a,x)})}function v(e){for(var t,n,r,i=e.length,o=T.relative[e[0].type],a=o||T.relative[" "],s=o?1:0,u=p(function(e){return e===t},a,!0),l=p(function(e){return ee(t,e)>-1},a,!0),c=[function(e,n,r){var i=!o&&(r||n!==A)||((t=n).nodeType?u(e,n,r):l(e,n,r));return t=null,i}];s1&&h(c),s>1&&d(e.slice(0,s-1).concat({value:" "===e[s-2].type?"*":""})).replace(se,"$1"),n,s0,o=e.length>0,a=function(r,a,s,u,l){var c,f,d,p=0,h="0",g=r&&[],y=[],v=A,x=r||o&&T.find.TAG("*",l),b=W+=null==v?1:Math.random()||.1,w=x.length;for(l&&(A=a===H||a||l);h!==w&&null!=(c=x[h]);h++){if(o&&c){for(f=0,a||c.ownerDocument===H||(L(c),s=!_);d=e[f++];)if(d(c,a||H,s)){u.push(c);break}l&&(W=b)}i&&((c=!d&&c)&&p--,r&&g.push(c))}if(p+=h,i&&h!==p){for(f=0;d=n[f++];)d(g,y,a,s);if(r){if(p>0)for(;h--;)g[h]||y[h]||(y[h]=G.call(u));y=m(y)}Q.apply(u,y),l&&!r&&y.length>0&&p+n.length>1&&t.uniqueSort(u)}return l&&(W=b,A=v),g};return i?r(a):a}var b,w,T,C,E,N,k,S,A,D,j,L,H,q,_,F,M,O,R,P="sizzle"+1*new Date,B=e.document,W=0,I=0,$=n(),z=n(),X=n(),U=function(e,t){return e===t&&(j=!0),0},V=1<<31,Y={}.hasOwnProperty,J=[],G=J.pop,K=J.push,Q=J.push,Z=J.slice,ee=function(e,t){for(var n=0,r=e.length;n+~]|"+ne+")"+ne+"*"),ce=new RegExp("="+ne+"*([^\\]'\"]*?)"+ne+"*\\]","g"),fe=new RegExp(oe),de=new RegExp("^"+re+"$"),pe={ID:new RegExp("^#("+re+")"),CLASS:new RegExp("^\\.("+re+")"),TAG:new RegExp("^("+re+"|[*])"),ATTR:new RegExp("^"+ie),PSEUDO:new RegExp("^"+oe),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+ne+"*(even|odd|(([+-]|)(\\d*)n|)"+ne+"*(?:([+-]|)"+ne+"*(\\d+)|))"+ne+"*\\)|)","i"),bool:new RegExp("^(?:"+te+")$","i"),needsContext:new RegExp("^"+ne+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+ne+"*((?:-\\d)?\\d*)"+ne+"*\\)|)(?=[^-]|$)","i")},he=/^(?:input|select|textarea|button)$/i,ge=/^h\d$/i,me=/^[^{]+\{\s*\[native \w/,ye=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ve=/[+~]/,xe=/'|\\/g,be=new RegExp("\\\\([\\da-f]{1,6}"+ne+"?|("+ne+")|.)","ig"),we=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},Te=function(){L()};try{Q.apply(J=Z.call(B.childNodes),B.childNodes),J[B.childNodes.length].nodeType}catch(Ce){Q={apply:J.length?function(e,t){K.apply(e,Z.call(t))}:function(e,t){for(var n=e.length,r=0;e[n++]=t[r++];);e.length=n-1}}}w=t.support={},E=t.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return!!t&&"HTML"!==t.nodeName},L=t.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:B;return r!==H&&9===r.nodeType&&r.documentElement?(H=r,q=H.documentElement,_=!E(H),(n=H.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",Te,!1):n.attachEvent&&n.attachEvent("onunload",Te)),w.attributes=i(function(e){return e.className="i",!e.getAttribute("className")}),w.getElementsByTagName=i(function(e){return e.appendChild(H.createComment("")),!e.getElementsByTagName("*").length}),w.getElementsByClassName=me.test(H.getElementsByClassName),w.getById=i(function(e){return q.appendChild(e).id=P,!H.getElementsByName||!H.getElementsByName(P).length}),w.getById?(T.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&_){var n=t.getElementById(e);return n?[n]:[]}},T.filter.ID=function(e){var t=e.replace(be,we);return function(e){return e.getAttribute("id")===t}}):(delete T.find.ID,T.filter.ID=function(e){var t=e.replace(be,we);return function(e){var n="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return n&&n.value===t}}),T.find.TAG=w.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):w.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){for(;n=o[i++];)1===n.nodeType&&r.push(n);return r}return o},T.find.CLASS=w.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&_)return t.getElementsByClassName(e)},M=[],F=[],(w.qsa=me.test(H.querySelectorAll))&&(i(function(e){q.appendChild(e).innerHTML=" ",e.querySelectorAll("[msallowcapture^='']").length&&F.push("[*^$]="+ne+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||F.push("\\["+ne+"*(?:value|"+te+")"),e.querySelectorAll("[id~="+P+"-]").length||F.push("~="),e.querySelectorAll(":checked").length||F.push(":checked"),e.querySelectorAll("a#"+P+"+*").length||F.push(".#.+[+~]")}),i(function(e){var t=H.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&F.push("name"+ne+"*[*^$|!~]?="),e.querySelectorAll(":enabled").length||F.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),F.push(",.*:")})),(w.matchesSelector=me.test(O=q.matches||q.webkitMatchesSelector||q.mozMatchesSelector||q.oMatchesSelector||q.msMatchesSelector))&&i(function(e){w.disconnectedMatch=O.call(e,"div"),O.call(e,"[s!='']:x"),M.push("!=",oe)}),F=F.length&&new RegExp(F.join("|")),M=M.length&&new RegExp(M.join("|")),t=me.test(q.compareDocumentPosition),R=t||me.test(q.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)for(;t=t.parentNode;)if(t===e)return!0;return!1},U=t?function(e,t){if(e===t)return j=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n?n:(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1,1&n||!w.sortDetached&&t.compareDocumentPosition(e)===n?e===H||e.ownerDocument===B&&R(B,e)?-1:t===H||t.ownerDocument===B&&R(B,t)?1:D?ee(D,e)-ee(D,t):0:4&n?-1:1)}:function(e,t){if(e===t)return j=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,s=[e],u=[t];if(!i||!o)return e===H?-1:t===H?1:i?-1:o?1:D?ee(D,e)-ee(D,t):0;if(i===o)return a(e,t);for(n=e;n=n.parentNode;)s.unshift(n);for(n=t;n=n.parentNode;)u.unshift(n);for(;s[r]===u[r];)r++;return r?a(s[r],u[r]):s[r]===B?-1:u[r]===B?1:0},H):H},t.matches=function(e,n){return t(e,null,null,n)},t.matchesSelector=function(e,n){if((e.ownerDocument||e)!==H&&L(e),n=n.replace(ce,"='$1']"),w.matchesSelector&&_&&!X[n+" "]&&(!M||!M.test(n))&&(!F||!F.test(n)))try{var r=O.call(e,n);if(r||w.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(i){}return t(n,H,null,[e]).length>0},t.contains=function(e,t){return(e.ownerDocument||e)!==H&&L(e),R(e,t)},t.attr=function(e,t){(e.ownerDocument||e)!==H&&L(e);var n=T.attrHandle[t.toLowerCase()],r=n&&Y.call(T.attrHandle,t.toLowerCase())?n(e,t,!_):void 0;return void 0!==r?r:w.attributes||!_?e.getAttribute(t):(r=e.getAttributeNode(t))&&r.specified?r.value:null},t.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},t.uniqueSort=function(e){var t,n=[],r=0,i=0;if(j=!w.detectDuplicates,D=!w.sortStable&&e.slice(0),e.sort(U),j){for(;t=e[i++];)t===e[i]&&(r=n.push(i));for(;r--;)e.splice(n[r],1)}return D=null,e},C=t.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=C(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r++];)n+=C(t);return n},T=t.selectors={cacheLength:50,createPseudo:r,match:pe,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(be,we),e[3]=(e[3]||e[4]||e[5]||"").replace(be,we),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||t.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&t.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return pe.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&fe.test(n)&&(t=N(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(be,we).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=$[e+" "];return t||(t=new RegExp("(^|"+ne+")"+e+"("+ne+"|$)"))&&$(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(e,n,r){return function(i){var o=t.attr(i,e);return null==o?"!="===n:!n||(o+="","="===n?o===r:"!="===n?o!==r:"^="===n?r&&0===o.indexOf(r):"*="===n?r&&o.indexOf(r)>-1:"$="===n?r&&o.slice(-r.length)===r:"~="===n?(" "+o.replace(ae," ")+" ").indexOf(r)>-1:"|="===n&&(o===r||o.slice(0,r.length+1)===r+"-"))}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,f,d,p,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!u&&!s,x=!1;if(m){if(o){for(;g;){for(d=t;d=d[g];)if(s?d.nodeName.toLowerCase()===y:1===d.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){for(d=m,f=d[P]||(d[P]={}),c=f[d.uniqueID]||(f[d.uniqueID]={}),
-l=c[e]||[],p=l[0]===W&&l[1],x=p&&l[2],d=p&&m.childNodes[p];d=++p&&d&&d[g]||(x=p=0)||h.pop();)if(1===d.nodeType&&++x&&d===t){c[e]=[W,p,x];break}}else if(v&&(d=t,f=d[P]||(d[P]={}),c=f[d.uniqueID]||(f[d.uniqueID]={}),l=c[e]||[],p=l[0]===W&&l[1],x=p),x===!1)for(;(d=++p&&d&&d[g]||(x=p=0)||h.pop())&&((s?d.nodeName.toLowerCase()!==y:1!==d.nodeType)||!++x||(v&&(f=d[P]||(d[P]={}),c=f[d.uniqueID]||(f[d.uniqueID]={}),c[e]=[W,x]),d!==t)););return x-=i,x===r||x%r===0&&x/r>=0}}},PSEUDO:function(e,n){var i,o=T.pseudos[e]||T.setFilters[e.toLowerCase()]||t.error("unsupported pseudo: "+e);return o[P]?o(n):o.length>1?(i=[e,e,"",n],T.setFilters.hasOwnProperty(e.toLowerCase())?r(function(e,t){for(var r,i=o(e,n),a=i.length;a--;)r=ee(e,i[a]),e[r]=!(t[r]=i[a])}):function(e){return o(e,0,i)}):o}},pseudos:{not:r(function(e){var t=[],n=[],i=k(e.replace(se,"$1"));return i[P]?r(function(e,t,n,r){for(var o,a=i(e,null,r,[]),s=e.length;s--;)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,r,o){return t[0]=e,i(t,null,o,n),t[0]=null,!n.pop()}}),has:r(function(e){return function(n){return t(e,n).length>0}}),contains:r(function(e){return e=e.replace(be,we),function(t){return(t.textContent||t.innerText||C(t)).indexOf(e)>-1}}),lang:r(function(e){return de.test(e||"")||t.error("unsupported lang: "+e),e=e.replace(be,we).toLowerCase(),function(t){var n;do if(n=_?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===q},focus:function(e){return e===H.activeElement&&(!H.hasFocus||H.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!T.pseudos.empty(e)},header:function(e){return ge.test(e.nodeName)},input:function(e){return he.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:l(function(){return[0]}),last:l(function(e,t){return[t-1]}),eq:l(function(e,t,n){return[n<0?n+t:n]}),even:l(function(e,t){for(var n=0;n=0;)e.push(r);return e}),gt:l(function(e,t,n){for(var r=n<0?n+t:n;++r2&&"ID"===(a=o[0]).type&&w.getById&&9===t.nodeType&&_&&T.relative[o[1].type]){if(t=(T.find.ID(a.matches[0].replace(be,we),t)||[])[0],!t)return n;l&&(t=t.parentNode),e=e.slice(o.shift().value.length)}for(i=pe.needsContext.test(e)?0:o.length;i--&&(a=o[i],!T.relative[s=a.type]);)if((u=T.find[s])&&(r=u(a.matches[0].replace(be,we),ve.test(o[0].type)&&c(t.parentNode)||t))){if(o.splice(i,1),e=r.length&&d(o),!e)return Q.apply(n,r),n;break}}return(l||k(e,f))(r,t,!_,n,!t||ve.test(e)&&c(t.parentNode)||t),n},w.sortStable=P.split("").sort(U).join("")===P,w.detectDuplicates=!!j,L(),w.sortDetached=i(function(e){return 1&e.compareDocumentPosition(H.createElement("div"))}),i(function(e){return e.innerHTML=" ","#"===e.firstChild.getAttribute("href")})||o("type|href|height|width",function(e,t,n){if(!n)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),w.attributes&&i(function(e){return e.innerHTML=" ",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||o("value",function(e,t,n){if(!n&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),i(function(e){return null==e.getAttribute("disabled")})||o(te,function(e,t,n){var r;if(!n)return e[t]===!0?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),t}(e);pe.find=ve,pe.expr=ve.selectors,pe.expr[":"]=pe.expr.pseudos,pe.uniqueSort=pe.unique=ve.uniqueSort,pe.text=ve.getText,pe.isXMLDoc=ve.isXML,pe.contains=ve.contains;var xe=function(e,t,n){for(var r=[],i=void 0!==n;(e=e[t])&&9!==e.nodeType;)if(1===e.nodeType){if(i&&pe(e).is(n))break;r.push(e)}return r},be=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},we=pe.expr.match.needsContext,Te=/^<([\w-]+)\s*\/?>(?:<\/\1>|)$/,Ce=/^.[^:#\[\.,]*$/;pe.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?pe.find.matchesSelector(r,e)?[r]:[]:pe.find.matches(e,pe.grep(t,function(e){return 1===e.nodeType}))},pe.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if("string"!=typeof e)return this.pushStack(pe(e).filter(function(){for(t=0;t1?pe.unique(n):n),n.selector=this.selector?this.selector+" "+e:e,n},filter:function(e){return this.pushStack(r(this,e||[],!1))},not:function(e){return this.pushStack(r(this,e||[],!0))},is:function(e){return!!r(this,"string"==typeof e&&we.test(e)?pe(e):e||[],!1).length}});var Ee,Ne=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,ke=pe.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||Ee,"string"==typeof e){if(r="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:Ne.exec(e),!r||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof pe?t[0]:t,pe.merge(this,pe.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:re,!0)),Te.test(r[1])&&pe.isPlainObject(t))for(r in t)pe.isFunction(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}if(i=re.getElementById(r[2]),i&&i.parentNode){if(i.id!==r[2])return Ee.find(e);this.length=1,this[0]=i}return this.context=re,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):pe.isFunction(e)?"undefined"!=typeof n.ready?n.ready(e):e(pe):(void 0!==e.selector&&(this.selector=e.selector,this.context=e.context),pe.makeArray(e,this))};ke.prototype=pe.fn,Ee=pe(re);var Se=/^(?:parents|prev(?:Until|All))/,Ae={children:!0,contents:!0,next:!0,prev:!0};pe.fn.extend({has:function(e){var t,n=pe(e,this),r=n.length;return this.filter(function(){for(t=0;t-1:1===n.nodeType&&pe.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(o.length>1?pe.uniqueSort(o):o)},index:function(e){return e?"string"==typeof e?pe.inArray(this[0],pe(e)):pe.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(pe.uniqueSort(pe.merge(this.get(),pe(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),pe.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return xe(e,"parentNode")},parentsUntil:function(e,t,n){return xe(e,"parentNode",n)},next:function(e){return i(e,"nextSibling")},prev:function(e){return i(e,"previousSibling")},nextAll:function(e){return xe(e,"nextSibling")},prevAll:function(e){return xe(e,"previousSibling")},nextUntil:function(e,t,n){return xe(e,"nextSibling",n)},prevUntil:function(e,t,n){return xe(e,"previousSibling",n)},siblings:function(e){return be((e.parentNode||{}).firstChild,e)},children:function(e){return be(e.firstChild)},contents:function(e){return pe.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:pe.merge([],e.childNodes)}},function(e,t){pe.fn[e]=function(n,r){var i=pe.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=pe.filter(r,i)),this.length>1&&(Ae[e]||(i=pe.uniqueSort(i)),Se.test(e)&&(i=i.reverse())),this.pushStack(i)}});var De=/\S+/g;pe.Callbacks=function(e){e="string"==typeof e?o(e):pe.extend({},e);var t,n,r,i,a=[],s=[],u=-1,l=function(){for(i=e.once,r=t=!0;s.length;u=-1)for(n=s.shift();++u-1;)a.splice(n,1),n<=u&&u--}),this},has:function(e){return e?pe.inArray(e,a)>-1:a.length>0},empty:function(){return a&&(a=[]),this},disable:function(){return i=s=[],a=n="",this},disabled:function(){return!a},lock:function(){return i=!0,n||c.disable(),this},locked:function(){return!!i},fireWith:function(e,n){return i||(n=n||[],n=[e,n.slice?n.slice():n],s.push(n),t||l()),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!r}};return c},pe.extend({Deferred:function(e){var t=[["resolve","done",pe.Callbacks("once memory"),"resolved"],["reject","fail",pe.Callbacks("once memory"),"rejected"],["notify","progress",pe.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return pe.Deferred(function(n){pe.each(t,function(t,o){var a=pe.isFunction(e[t])&&e[t];i[o[1]](function(){var e=a&&a.apply(this,arguments);e&&pe.isFunction(e.promise)?e.promise().progress(n.notify).done(n.resolve).fail(n.reject):n[o[0]+"With"](this===r?n.promise():this,a?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?pe.extend(e,r):r}},i={};return r.pipe=r.then,pe.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t,n,r,i=0,o=ie.call(arguments),a=o.length,s=1!==a||e&&pe.isFunction(e.promise)?a:0,u=1===s?e:pe.Deferred(),l=function(e,n,r){return function(i){n[e]=this,r[e]=arguments.length>1?ie.call(arguments):i,r===t?u.notifyWith(n,r):--s||u.resolveWith(n,r)}};if(a>1)for(t=new Array(a),n=new Array(a),r=new Array(a);i0||(je.resolveWith(re,[pe]),pe.fn.triggerHandler&&(pe(re).triggerHandler("ready"),pe(re).off("ready"))))}}),pe.ready.promise=function(t){if(!je)if(je=pe.Deferred(),"complete"===re.readyState||"loading"!==re.readyState&&!re.documentElement.doScroll)e.setTimeout(pe.ready);else if(re.addEventListener)re.addEventListener("DOMContentLoaded",s),e.addEventListener("load",s);else{re.attachEvent("onreadystatechange",s),e.attachEvent("onload",s);var n=!1;try{n=null==e.frameElement&&re.documentElement}catch(r){}n&&n.doScroll&&!function i(){if(!pe.isReady){try{n.doScroll("left")}catch(t){return e.setTimeout(i,50)}a(),pe.ready()}}()}return je.promise(t)},pe.ready.promise();var Le;for(Le in pe(fe))break;fe.ownFirst="0"===Le,fe.inlineBlockNeedsLayout=!1,pe(function(){var e,t,n,r;n=re.getElementsByTagName("body")[0],n&&n.style&&(t=re.createElement("div"),r=re.createElement("div"),r.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",n.appendChild(r).appendChild(t),"undefined"!=typeof t.style.zoom&&(t.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",fe.inlineBlockNeedsLayout=e=3===t.offsetWidth,e&&(n.style.zoom=1)),n.removeChild(r))}),function(){var e=re.createElement("div");fe.deleteExpando=!0;try{delete e.test}catch(t){fe.deleteExpando=!1}e=null}();var He=function(e){var t=pe.noData[(e.nodeName+" ").toLowerCase()],n=+e.nodeType||1;return(1===n||9===n)&&(!t||t!==!0&&e.getAttribute("classid")===t)},qe=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,_e=/([A-Z])/g;pe.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(e){return e=e.nodeType?pe.cache[e[pe.expando]]:e[pe.expando],!!e&&!l(e)},data:function(e,t,n){return c(e,t,n)},removeData:function(e,t){return f(e,t)},_data:function(e,t,n){return c(e,t,n,!0)},_removeData:function(e,t){return f(e,t,!0)}}),pe.fn.extend({data:function(e,t){var n,r,i,o=this[0],a=o&&o.attributes;if(void 0===e){if(this.length&&(i=pe.data(o),1===o.nodeType&&!pe._data(o,"parsedAttrs"))){for(n=a.length;n--;)a[n]&&(r=a[n].name,0===r.indexOf("data-")&&(r=pe.camelCase(r.slice(5)),u(o,r,i[r])));pe._data(o,"parsedAttrs",!0)}return i}return"object"==typeof e?this.each(function(){pe.data(this,e)}):arguments.length>1?this.each(function(){pe.data(this,e,t)}):o?u(o,e,pe.data(o,e)):void 0},removeData:function(e){return this.each(function(){pe.removeData(this,e)})}}),pe.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=pe._data(e,t),n&&(!r||pe.isArray(n)?r=pe._data(e,t,pe.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=pe.queue(e,t),r=n.length,i=n.shift(),o=pe._queueHooks(e,t),a=function(){pe.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return pe._data(e,n)||pe._data(e,n,{empty:pe.Callbacks("once memory").add(function(){pe._removeData(e,t+"queue"),pe._removeData(e,n)})})}}),pe.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),arguments.length a ",fe.leadingWhitespace=3===e.firstChild.nodeType,fe.tbody=!e.getElementsByTagName("tbody").length,fe.htmlSerialize=!!e.getElementsByTagName("link").length,fe.html5Clone="<:nav>"!==re.createElement("nav").cloneNode(!0).outerHTML,n.type="checkbox",n.checked=!0,t.appendChild(n),fe.appendChecked=n.checked,e.innerHTML="",fe.noCloneChecked=!!e.cloneNode(!0).lastChild.defaultValue,t.appendChild(e),n=re.createElement("input"),n.setAttribute("type","radio"),n.setAttribute("checked","checked"),n.setAttribute("name","t"),e.appendChild(n),fe.checkClone=e.cloneNode(!0).cloneNode(!0).lastChild.checked,fe.noCloneEvent=!!e.addEventListener,e[pe.expando]=1,fe.attributes=!e.getAttribute(pe.expando)}();var Xe={option:[1,""," "],legend:[1,""," "],area:[1,""," "],param:[1,""," "],thead:[1,""],tr:[2,""],col:[2,""],td:[3,""],_default:fe.htmlSerialize?[0,"",""]:[1,"X","
"]};Xe.optgroup=Xe.option,Xe.tbody=Xe.tfoot=Xe.colgroup=Xe.caption=Xe.thead,Xe.th=Xe.td;var Ue=/<|?\w+;/,Ve=/-1&&(h=p.split("."),p=h.shift(),h.sort()),a=p.indexOf(":")<0&&"on"+p,t=t[pe.expando]?t:new pe.Event(p,"object"==typeof t&&t),t.isTrigger=i?2:3,t.namespace=h.join("."),t.rnamespace=t.namespace?new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=void 0,t.target||(t.target=r),n=null==n?[t]:pe.makeArray(n,[t]),l=pe.event.special[p]||{},i||!l.trigger||l.trigger.apply(r,n)!==!1)){if(!i&&!l.noBubble&&!pe.isWindow(r)){for(u=l.delegateType||p,Ke.test(u+p)||(s=s.parentNode);s;s=s.parentNode)d.push(s),c=s;c===(r.ownerDocument||re)&&d.push(c.defaultView||c.parentWindow||e)}for(f=0;(s=d[f++])&&!t.isPropagationStopped();)t.type=f>1?u:l.bindType||p,o=(pe._data(s,"events")||{})[t.type]&&pe._data(s,"handle"),o&&o.apply(s,n),o=a&&s[a],o&&o.apply&&He(s)&&(t.result=o.apply(s,n),t.result===!1&&t.preventDefault());if(t.type=p,!i&&!t.isDefaultPrevented()&&(!l._default||l._default.apply(d.pop(),n)===!1)&&He(r)&&a&&r[p]&&!pe.isWindow(r)){c=r[a],c&&(r[a]=null),pe.event.triggered=p;try{r[p]()}catch(g){}pe.event.triggered=void 0,c&&(r[a]=c)}return t.result}},dispatch:function(e){e=pe.event.fix(e);var t,n,r,i,o,a=[],s=ie.call(arguments),u=(pe._data(this,"events")||{})[e.type]||[],l=pe.event.special[e.type]||{};if(s[0]=e,e.delegateTarget=this,!l.preDispatch||l.preDispatch.call(this,e)!==!1){for(a=pe.event.handlers.call(this,e,u),t=0;(i=a[t++])&&!e.isPropagationStopped();)for(e.currentTarget=i.elem,n=0;(o=i.handlers[n++])&&!e.isImmediatePropagationStopped();)e.rnamespace&&!e.rnamespace.test(o.namespace)||(e.handleObj=o,e.data=o.data,r=((pe.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,s),void 0!==r&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()));return l.postDispatch&&l.postDispatch.call(this,e),e.result}},handlers:function(e,t){var n,r,i,o,a=[],s=t.delegateCount,u=e.target;if(s&&u.nodeType&&("click"!==e.type||isNaN(e.button)||e.button<1))for(;u!=this;u=u.parentNode||this)if(1===u.nodeType&&(u.disabled!==!0||"click"!==e.type)){for(r=[],n=0;n-1:pe.find(i,this,null,[u]).length),r[i]&&r.push(o);r.length&&a.push({elem:u,handlers:r})}return s ]","i"),tt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,nt=/
diff --git a/docs/.template/index.md b/docs/.template/index.md
new file mode 100644
index 000000000..543402347
--- /dev/null
+++ b/docs/.template/index.md
@@ -0,0 +1,64 @@
+---
+title: 组件中文名 组件名
+toc: true
+---
+
+# 组件中文名
+
+> 组件介绍
+
+示例
+
+
+{{- d.include("/组件名/detail/demo.md") }}
+
+
+API
+
+| API | 描述 |
+| --- | --- |
+| const { 组件名 } = layui | 获得 `组件名` 模块。 |
+| [组件名.render(options)](#render) | 组件名 组件渲染,核心方法。 |
+| …… | …… |
+
+渲染
+
+`组件名.render(options);`
+
+- 参数 `options` : 基础选项。[#详见选项](#options)
+
+选项
+
+
+{{- d.include("/组件名/detail/options.md") }}
+
+
+_更多方法的详细介绍_
+
+方法传入的参数(`opts`)是一个 `Object` 类型的选项,需按照表格的方式展示,如:
+
+```markdown
+| 选项 | 描述 | 类型 | 默认值 |
+| --- | --- | --- | --- |
+| 选项名 | 该选项的详细介绍 | 该选项支持的数据类型 | 该选项的默认值,若无则填写 `-` |
+```
+
+## 事件
+
+_若有的话_
+
+| 事件名 | 描述 |
+| --- | --- |
+| eventName | 描述 |
+
+事件名
+
+触发时机的描述,若事件支持阻断机制(`return false`),必须在文档中明确说明。
+
+```js
+// 示例代码
+```
+
+## 💖 心语
+
+通常是开发者开发该组件时的内心独白,通过带有感性化的文字与受众建立奇妙的意识沟通。
\ No newline at end of file
diff --git a/docs/README.md b/docs/README.md
new file mode 100644
index 000000000..2668c792b
--- /dev/null
+++ b/docs/README.md
@@ -0,0 +1,6 @@
+# Layui 文档
+
+## 预览
+
+- [最新](https://layui.dev/docs/)
+- [2.x](https://layui.dev/docs/2/)
\ No newline at end of file
diff --git a/docs/anim/index.md b/docs/anim/index.md
new file mode 100644
index 000000000..2f18177e1
--- /dev/null
+++ b/docs/anim/index.md
@@ -0,0 +1,139 @@
+---
+title: 动画
+toc: true
+---
+
+
+
+# 动画
+
+> Layui 内置了几种常见的 `CSS3` 动画。
+
+示例
+
+
+
+
+
+对需要动画的标签添加 `class="lay-anim"` 基础类,再追加其他不同的动画类,即可让元素产生动画。
+
+动画列表
+
+点击下述绿色圆体,即可预览不同类名的动画效果。
+
+
+
+
+
+
+
diff --git a/docs/auxiliar/index.md b/docs/auxiliar/index.md
new file mode 100644
index 000000000..04fccb8ff
--- /dev/null
+++ b/docs/auxiliar/index.md
@@ -0,0 +1,70 @@
+---
+title: 辅助元素 blockquote,fieldset,hr
+toc: true
+---
+
+# 辅助元素
+
+> 辅助元素是指对 `blockquote,fieldset,hr` 等标签的美化,主要是静态展示作用。
+
+引用
+
+
+
+
+
+字段集
+
+
+
+
+
+
+水平线
+
+
+
+
diff --git a/docs/badge/index.md b/docs/badge/index.md
new file mode 100644
index 000000000..03564b00f
--- /dev/null
+++ b/docs/badge/index.md
@@ -0,0 +1,89 @@
+---
+title: 徽章 badge
+toc: true
+---
+
+# 徽章
+
+> 徽章 `badge` 通常作为修饰用途而存在,它们本身细小而并不显眼,但掺杂在其它元素中就显得尤为突出了。
+
+
+普通徽章
+
+
+
+
+
+
+小圆点
+
+
+
+
+
+
+徽章的搭配
+
+
+
+
+
+徽章还可以自由佩戴在其他更多元素中,此处不做逐一列举。
+
+
diff --git a/docs/base.md b/docs/base.md
new file mode 100644
index 000000000..ac4d87419
--- /dev/null
+++ b/docs/base.md
@@ -0,0 +1,166 @@
+---
+title: 底层方法
+toc: true
+---
+
+# 底层方法
+
+> Layui 提供了一系列基础 API,以更好地辅助组件的使用。
+
+全局配置
+
+`layui.config(options);`
+
+您可以在 Layui 模块使用之前,采用该方法进行一些全局化的基础配置,其支持的属性如下:
+
+```
+layui.config({
+ base: '', // 设定 Layui 扩展模块的所在目录,一般与 extend 方法搭配使用
+ version: false, // 用于更新模块缓存,默认 false。若设为 true,即让浏览器不缓存。也可设为一个任意数值
+ dir: 'layui/', // layui 基础目录,用于动态导入 src/layui.js 时的内置模块的加载。一般无需设置
+ debug: false // 用于开启调试模式,默认 false。若设为 true,则模块的引入节点会保留在页面
+});
+```
+
+
+
+
+链接解析
+
+`var url = layui.url(href);`
+
+参数 `href` 可选,默认自动读取当前页面 URL(`location.href`)。该方法用于将一段 URL 链接中的 `pathname、search、hash` 等属性进行对象化处理, 以下是对一个 URL 解析后的返回结果:
+
+```
+// 假设当前页面 url 为: https://domain.com/docs/base.html?a=1&c=3#/user/set/id=123/
+var url = layui.url();
+
+// url 返回结果为:
+{
+ "pathname": ["docs","base.html"], // 路径
+ "search": {"a":"1","c":"3"}, // 参数
+ "hash": { // hash 解析
+ "path": ["user","set",""], // hash 中的路径
+ "search": {"id":"123"}, // hash 中的参数
+ "hash": "", // hash 中的 hash
+ "href": "/user/set/id=123/" // hash 中的完整链接
+ }
+}
+```
+
+该方法通常可搭配 `location.hash` 和 `hashchange ` 事件,或 `history.pushState()` 和 `popstate` 事件使用,从而实现*单页面应用开发*。 Layui 的 AdminUI 主题模板则正是基于该方法完成的路由系统。
+
+
+本地存储
+
+本地存储是对 localStorage 和 sessionStorage 的友好封装,可更方便地管理本地数据。方法如下:
+
+- `layui.data(table, settings);` 即 localStorage,数据在浏览器中的持久化存储,除非物理删除。
+- `layui.sessionData(table, settings);` 即 sessionStorage ,数据在浏览器中的会话性存储,页面关闭后即失效。
+
+两者使用方式完全一致。其中参数 `table` 为表名,`settings` 是一个对象,用于设置 `key/value`。下面以 `layui.data()` 方法为例:
+
+```
+// 【增】:向 test 表插入一个 nickname 字段,如果该表不存在,则自动建立。
+layui.data('test', {
+ key: 'nickname',
+ value: '张三'
+});
+
+// 【删】:删除 test 表的 nickname 字段
+layui.data('test', {
+ key: 'nickname',
+ remove: true
+});
+layui.data('test', null); // 删除 test 表
+
+// 【改】:同【增】,会覆盖已经存储的数据
+
+// 【查】:向 test 表读取全部的数据
+var localTest = layui.data('test');
+console.log(localTest.nickname); // 获得“张三”
+```
+
+浏览器信息
+
+`var device = layui.device(key);`
+
+参数 `key` 可选。可利用该方法对不同的设备进行差异化处理,`device` 即为不同设备下返回的不同信息,如下:
+
+```
+{
+ os: "windows", // 当前浏览器所在的底层操作系统,如:Windows、Linux、Mac 等
+ ie: false, // 当前浏览器是否为 ie6-11 的版本,如果不是 ie 浏览器,则为 false
+ weixin: false, // 当前浏览器是否为微信 App 环境
+ android: false, // 当前浏览器是否为安卓系统环境
+ ios: false, // 当前浏览器是否为 IOS 系统环境
+ mobile: false // 当前浏览器是否为移动设备环境(v2.5.7 新增)
+}
+```
+
+有时,你的 App 可能会对 userAgent 插入一段特定标识,如:
+
+```
+Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 MYAPP/1.8.6 Safari/537.36
+```
+
+要验证当前页面是否在你的 App 环境中,即可通过上述 `MYAPP`(即 Native 给 Webview 插入的标识,可自由定义)来判断。
+
+```
+var device = layui.device('MYAPP');
+if(device.MYAPP){
+ alert('在 MYAPP 环境中');
+}
+```
+
+API 列表
+
+前面我们特别介绍了几个相对特殊的基础方法,而以下是 Layui 提供的全部基础 API:
+
+| API | 描述 |
+| --- | --- |
+| layui.cache | 获得 UI 的一些配置及临时缓存信息 |
+| layui.config(options) | 基础配置。[#用法](#config) |
+| layui.define([modules], callback) | 定义模块。[#用法](modules.html#define) |
+| layui.use([modules], callback) | 加载模块。[#用法](modules.html#use) |
+| layui.extend(obj) | 扩展模块。[#用法](modules.html#extend) |
+| layui.disuse([modules]) 2.7+ | 弃用模块,以便重新扩展新的同名模块。参数支持数组,即可同时弃用多个模块。 如:`layui.disuse(['table'])` |
+| layui.link(href) | 加载 CSS,`href` 即为 css 路径。一般用于动态加载你的外部 CSS 文件 |
+| layui.getStyle(node, name) | 获得一个原始 DOM 节点的 style 属性值,如: `layui.getStyle(document.body, 'font-size')` |
+| layui.img(src, callback, error) | 图片预加载 |
+| layui.each(obj, callback) | 对象(Array、Object、DOM 对象等)遍历,可用于取代 for 语句 |
+| layui.type(operand) 2.6.7+ | 获取基本数据类型和各类常见引用类型,如: `layui.type([]); // array` `layui.type({}); //object` `layui.type(new Date()); // date` |
+| layui.isArray(obj) 2.7+ | 对象是否为泛数组结构。如 Array、NodeList、jQuery 对象等 `layui.isArray([1,6]); // true` `layui.isArray($('div')); // true` |
+| layui.sort(obj, key, desc) | 将数组中的对象按某个成员重新对该数组排序,如:`layui.sort([{a: 3},{a: 1},{a: 5}], 'a'); // 返回:[{"a":1},{"a":3},{"a":5}]` |
+| layui.url(href) | 链接解析。[#用法](#url) |
+| layui.data(table, settings) | 持久化存储。[#用法](#data) |
+| layui.sessionData(table, settings) | 会话性存储。[#用法](#data) |
+| layui.device(key) | 获取浏览器信息。[#用法](#device) |
+| layui.hint() | 向控制台打印一些异常信息,目前只返回了 error 方法,如: `var hint = layui.hint();` `hint.error('出错啦');` |
+| layui.onevent(modName, events, callback) | 增加自定义模块事件,一般在内置组件中使用。 |
+| layui.event(modName, events, params) | 执行自定义模块事件,搭配 onevent 使用。注2.8+ :当 events 参数中未设定 filter 时则可重复执行该事件,否则只会执行一次最新添加的事件。 |
+| layui.off(events, modName) 2.5.7+ | 用于移除模块相关事件,如:`layui.off('select(filter)', 'form')`,那么`form.on('select(filter)', callback)`事件将会被移除 |
+| layui.debounce(fn, wait) 2.8.3+ | 防抖,函数按指定毫秒延时执行 |
+| layui.throttle(fn, wait) 2.8.3+ | 节流,限制函数在指定毫秒内不重复执行 |
+| layui.getDefineCallback(modName) | 用于获取通过 `layui.define` 定义模块时的回调函数 |
+| layui.lay | 基础模块,提供了更多基础 API,一般供 Layui 内置组件中使用 |
+
+> 基础 API 是整个 UI 的有力支撑,我们在组件的使用过程中也经常会用到。
+
+
diff --git a/docs/button/index.md b/docs/button/index.md
new file mode 100644
index 000000000..09fe62a9b
--- /dev/null
+++ b/docs/button/index.md
@@ -0,0 +1,213 @@
+---
+title: 按钮
+toc: true
+---
+
+# 按钮
+
+> 向任意 `HTML` 标签设定`class="lay-btn"` 建立一个基础按钮。通过追加格式为`lay-btn-{type}`的 `class` 来定义其它按钮风格。内置的按钮 `class` 可以进行任意组合,从而形成更多种按钮风格。
+
+按钮主题
+
+
+
+
+
+按钮尺寸
+
+
+
+
+
+按钮圆角
+
+
+
+
+
+按钮图标
+
+
+
+
+
+按钮混搭
+
+
+
+
+
+按钮组合
+
+
+
+
+
+按钮容器
+
+
+
+
+
+
+
+## 小贴士
+
+> 按钮的主题、尺寸、图标、圆角的交叉组合,可以形成丰富多样的按钮种类。其中颜色也可以根据使用场景自主更改。
diff --git a/docs/carousel/detail/demo.md b/docs/carousel/detail/demo.md
new file mode 100644
index 000000000..926fb4712
--- /dev/null
+++ b/docs/carousel/detail/demo.md
@@ -0,0 +1,219 @@
+常规用法
+
+
+
+
+
+- 在元素外层设置 `class="lay-carousel"` 来定义一个轮播容器
+- 在元素内层设置属性 `carousel-item` 用来定义条目容器
+
+可选项预览
+
+
+
+
+
+填充图片轮播
+
+
+
+
+
diff --git a/docs/carousel/detail/options.md b/docs/carousel/detail/options.md
new file mode 100644
index 000000000..57bf9f919
--- /dev/null
+++ b/docs/carousel/detail/options.md
@@ -0,0 +1,239 @@
+
+
+
+
+
+
+
+
+
+ 属性名
+ 描述
+ 类型
+ 默认值
+
+
+
+
+elem
+
+
+绑定元素选择器或 DOM 对象
+
+
+string/DOM
+-
+
+
+width
+
+
+设定轮播容器宽度,值支持:*像素*、*auto*、*百分比*。
+
+
+string
+
+
+`600px`
+
+
+
+
+height
+
+
+设定轮播容器高度,值支持的类型同 `width` 属性
+
+
+string
+
+
+`280px`
+
+
+
+
+full
+
+
+是否全屏轮播
+
+
+boolean
+
+
+`false`
+
+
+
+
+anim
+
+
+轮播切换动画方式。可选值有:
+
+- `default` 左右切换
+- `updown` 上下切换
+- `fade` 渐隐渐显切换
+
+
+string
+
+
+`default`
+
+
+
+
+autoplay
+
+
+是否自动切换,可选值有:
+
+- `true` 自动滚动,鼠标移入会暂停、移出重新恢复
+- `false` 不自动滚动
+- `always` 始终自动滚动,不受鼠标移入移出影响 2.7+
+
+
+
+boolean string
+
+
+`true`
+
+
+
+
+interval
+
+
+自动切换的时间间隔,单位: ms (毫秒),不能低于 800
+
+
+number
+
+
+`3000`
+
+
+
+
+index
+
+
+初始开始的条目下标
+
+
+number
+
+
+`0`
+
+
+
+
+arrow
+
+
+切换箭头默认显示状态,可选值有:
+
+- `hover` 鼠标悬停显示
+- `always` 始终显示
+- `none` 始终不显示
+
+
+string
+
+
+`hover`
+
+
+
+
+indicator
+
+
+指示器位置,可选值有:
+
+- `inside` 显示在容器内部
+- `outside` 显示在容器外部
+- `none` 不显示
+
+注 : 若设定了 `anim: 'updown'` ,则 `outside` 值无效
+
+
+string
+
+
+`inside`
+
+
+
+
+trigger
+
+
+指示器的触发事件
+
+
+string
+
+
+`click`
+
+
+
+
+
+
+
+
+
+[回调函数](#options.callback)
+
+
+
+
+
+
+change 2.7+
+
+
+
+轮播切换后的回调函数,返回一个对象参数。
+
+
+```
+carousel.render({
+ elem: '#id',
+ change: function(obj){
+ console.log(obj.index); // 当前条目的索引
+ console.log(obj.prevIndex); // 上一个条目的索引
+ console.log(obj.item); // 当前条目的元素对象
+ }
+});
+```
+
+注:在 `2.7` 之前的版本,需通过 carousel 的 `change` 事件来实现,如:
+
+```
+var carousel = layui.carousel;
+
+// 轮播渲染
+carousel.render(options);
+
+// 触发轮播切换事件
+carousel.on('change(filter)', function(obj){ // filter 对应轮播容器的 lay-filter 属性值
+ console.log(obj);
+});
+```
+
+
+
+
+
+
+### 贴士
+
+> 若轮播的填充内容为图片,且 `width` 或 `height` 为自适应,那么需动态获取父容器宽高,从而适配父容器。 当浏览器窗口尺寸发生变化时,可在窗口 `resize` 事件中通过轮播重载来重设宽高值。
+
diff --git a/docs/carousel/index.md b/docs/carousel/index.md
new file mode 100644
index 000000000..8c0b1c262
--- /dev/null
+++ b/docs/carousel/index.md
@@ -0,0 +1,80 @@
+---
+title: 轮播组件 carousel
+toc: true
+---
+
+# 轮播组件
+
+> 轮播组件 `carousel` 主要适用于跑马灯/轮播等交互场景。它并非单纯地为焦点图而生,准确地说,它可以满足任何内容的轮播式切换操作,亦可胜任 `fullpage`(全屏上下轮播)的需求。
+
+示例
+
+
+
+
+{{- d.include("/carousel/detail/demo.md") }}
+
+
+API
+
+| API | 描述 |
+| --- | --- |
+| var carousel = layui.carousel | 获得 `carousel` 模块。 |
+| [基础接口](../component/#export) 2.13+ | 该组件由 `component` 构建,因此继承其提供的基础接口。|
+| [var inst = carousel.render(options)](#render) | carousel 组件渲染,核心方法。 |
+| [inst.reload(options)](#reload) | 轮播实例重载 |
+| [inst.goto(index)](#goto) 2.8+ | 轮播切换到特定下标 |
+
+渲染
+
+`carousel.render(options);`
+
+- 参数 `options` : 基础属性选项。[#详见属性](#options)
+
+该方法返回一个实例对象,包含操作当前实例的相关方法成员。
+
+```
+var inst = carousel.render(options);
+console.log(inst); // 得到当前实例对象
+```
+
+重载
+
+`inst.reload(options);`
+
+- 参数 `options` : 基础属性选项。[#详见属性](#options)
+
+通过渲染返回的实例对象,可获得重载方法,用于实现对实例的属性重载。
+
+```
+var inst = carousel.render(options); // 轮播初始渲染
+inst.reload(options); // 轮播重载
+```
+
+详细用法可参考:[#示例](#demo)
+
+属性
+
+
+{{- d.include("/carousel/detail/options.md") }}
+
+
+
+切换 2.8+
+
+`inst.goto(index);`
+
+- 参数 `index` : 轮播下标,从 `0` 开始计算
+
+通过渲染返回的实例对象,可获得切换方法,用于实现对轮播的手动定向切换。
+
+```
+var inst = carousel.render(options); // 轮播初始渲染
+inst.goto(0); // 轮播切换到第一项
+inst.goto(1); // 轮播切换到第二项
+```
diff --git a/docs/class/index.md b/docs/class/index.md
new file mode 100644
index 000000000..a23eae379
--- /dev/null
+++ b/docs/class/index.md
@@ -0,0 +1,231 @@
+---
+title: 公共类 class
+toc: true
+---
+
+# 公共类
+
+> 公共类是 `layui.css` 中并不以组件形式存在的公共 `class` 选择器,而又能用于任何地方。
+
+普通类
+
+| className | 描述 |
+| --- | --- |
+| lay-main | 设置一个固定宽度为 `1160px` 的水平居中块 |
+| lay-border-box | 设置元素及其所有子元素均为 `box-sizing: border-box` 模型的容器 |
+| lay-clear | 清除前面的同级元素产生的浮动 |
+| lay-clear-space 2.8+ | 清除容器内的空白符 |
+| lay-inline | 设置元素为内联块状结构 |
+| lay-ellip | 设置单行文本溢出并显示省略号 |
+| lay-unselect | 屏蔽选中 |
+| lay-disabled | 设置元素为不可点击状态 |
+| lay-circle | 设置元素为圆形。需确保 `width` 和 `height` 相同 |
+
+显示隐藏
+
+| className | 描述 |
+| --- | --- |
+| lay-show | 设置元素为 `display: block` 可见状态 |
+| lay-hide | 设置元素为 `display: none` 隐藏状态,且不占用空间 |
+| lay-show-v | 设置元素为 `visibility: visible` 可见状态 |
+| lay-hide-v | 设置元素为 `visibility: hidden` 不可见状态,且依旧占用空间 |
+
+
+三角实体
+
+| className | 描述 |
+| --- | --- |
+| lay-edge | 定义一个三角形基础类 |
+| lay-edge-top | 设置向上三角 |
+| lay-edge-right | 设置向右三角 |
+| lay-edge-bottom | 设置向下三角 |
+| lay-edge-left | 设置向左三角 |
+
+示例
+
+
+
+
+
+内外边距
+
+| className | 描述 |
+| --- | --- |
+| lay-padding-1 | 4px 内边距 |
+| lay-padding-2 | 8px 内边距 |
+| lay-padding-3 | 16px 内边距 |
+| lay-padding-4 | 32px 内边距 |
+| lay-padding-5 | 48px 内边距 |
+| lay-margin-1 | 4px 外边距 |
+| lay-margin-2 | 8px 外边距 |
+| lay-margin-3 | 16px 外边距 |
+| lay-margin-4 | 32px 外边距 |
+| lay-margin-5 | 48px 外边距 |
+
+
+背景颜色
+
+| className | 背景色 | 预览 |
+| --- | --- | --- |
+| lay-bg-red | 红 |
|
+| lay-bg-orange | 橙 |
|
+| lay-bg-green | 绿 |
|
+| lay-bg-blue | 蓝 |
|
+| lay-bg-purple 2.8+ | 紫 |
|
+| lay-bg-black | 深 |
|
+| lay-bg-gray | 浅 |
|
+
+文字大小
+
+| className | 文字大小和预览 |
+| --- | --- |
+| lay-font-12 | 12px |
+| lay-font-13 2.8+ | 13px |
+| lay-font-14 | 14px |
+| lay-font-16 | 16px |
+| lay-font-18 | 18px |
+| lay-font-20 | 20px |
+| lay-font-22 2.8+ | 22px |
+| lay-font-24 2.8+ | 24px |
+| lay-font-26 2.8+ | 26px |
+| lay-font-28 2.8+ | 28px |
+| lay-font-30 2.8+ | 30px |
+| lay-font-32 2.8+ | 32px |
+
+文字颜色
+
+| className | 文字颜色和预览 |
+| --- | --- |
+| lay-font-red | 红 |
+| lay-font-orange | 橙 |
+| lay-font-green | 绿 |
+| lay-font-blue | 蓝 |
+| lay-font-purple 2.8+ | 紫 |
+| lay-font-black | 深 |
+| lay-font-gray | 浅 |
+
+文本容器
+
+通过设置 `class="lay-text"` 定义一段包含标题、段落、列表等组合的文本区域,通常用于 Markdown 文档。
+
+
+
+
+
diff --git a/docs/code/detail/options.md b/docs/code/detail/options.md
new file mode 100644
index 000000000..2f3466743
--- /dev/null
+++ b/docs/code/detail/options.md
@@ -0,0 +1,461 @@
+
+
+
+
+
+
+
+
+
+ 属性名
+ 描述
+ 类型
+ 默认值
+
+
+
+
+elem
+
+
+绑定元素选择器或 DOM 对象
+
+
+string/DOM
+-
+
+
+code 2.8.18+
+
+
+设置原始 code 值,默认取目标元素中的内容
+
+
+string
+-
+
+
+preview 2.8+
+
+
+是否开启 Code 预览功能,可选值有:
+
+- `true` 开启 Code 的普通预览
+- `false` 关闭 Code 预览(默认)
+- `"iframe"` 开启 Code 在 iframe 模式中预览
+
+当开启该属性时,`elem` 指定的元素需要设置成以下结构:
+
+```
+
+
+
+```
+
+
+boolean string
+
+
+`false`
+
+
+
+
+layout 2.8+
+
+
+开启预览后的面板布局方式,值为一个数组,数组的可选成员有:
+
+- `code` 代码区域
+- `preview` 预览区域
+
+面板将根据数组的排列顺序来显示,如:
+
+```
+layout: ['code', 'preview']
+```
+
+
+array
+-
+
+
+style 2.8+
+
+
+设置 Code 和预览区域的公共样式
+
+
+string
+-
+
+
+codeStyle 2.8+
+
+
+设置 Code 区域的局部样式,优先级高于 `style` 属性
+
+
+string
+-
+
+
+previewStyle 2.8+
+
+
+设置预览区域的局部样式,优先级高于 `style` 属性
+
+
+string
+-
+
+
+id 2.8+
+
+
+设置实例的唯一索引,以便用于其他操作
+
+
+string
+-
+
+
+className 2.8+
+
+
+追加实例面板的 `className`,以便对其自定义样式
+
+
+string
+-
+
+
+tools
+
+
+用于设置组件右上角面板工具列表,仅 `preview: true` 时有效。值为一个数组,可选值(内置工具):
+
+- `copy` : 代码复制
+- `full` : 最大化显示
+- `window` : 在新窗口预览。一般当 `layout: 'iframe'` 时开启,且 code 中须包含完整的 HTML 方可在新窗口正常预览。
+
+工具图标将根据数组的排列顺序来显示,如:
+
+```js
+tools: ['full', 'window','copy']
+```
+
+
+array
+-
+
+
+extendToolkit
+
+
+用于扩展工具包。
+
+```js
+extendToolkit: {
+ // 主题工具
+ theme: {
+ title: ['切换高亮主题'], // 工具标题
+ iconName: 'theme', // 工具图标名
+ // 点击事件
+ onClick(obj) {
+ // do something
+ console.log(obj); // 当前实例相关信息
+ }
+ }
+}
+```
+
+选项解释:
+
+- `title` 值为数组形式,以支持不同状态时的默认标题
+- `iconName` 值对应[图标](../icon/) `className` 的 `lay-icon-` 后的名称。如图标:`lay-icon-theme`,那么 `iconName` 设置值为 `theme` 即可。
+
+扩展后,即可在 `tools` 选项中设置,如:`tools: ['theme']`
+
+
+object
+-
+
+
+onToolClick
+
+
+点击任意工具触发的回调函数。
+
+```js
+onToolClick: function(obj) {
+ console.log(obj); // 返回信息
+ console.log(obj.name); // 当前工具 name
+}
+```
+
+通过该函数与 `tools` 属性的搭配,可实现对工具栏的扩展。
+
+
+function
+-
+
+
+copy 2.8.2+
+
+
+用于开启代码复制功能图标。若开启 `priview`,则自动放置在 `tools` 属性中,复制图标将显示在容器右上角工具栏;若未开启 `priview`,则显示在 code 区域右上角。
+
+
+boolean
+
+
+`true`
+
+
+
+
+text 2.8+
+
+
+自定义默认文本,值为一个对象,可选成员有:
+
+```
+text: {
+ code: '代码栏标题', // 默认: >
+ preview: '预览栏标题' // 默认: Preview
+}
+```
+
+
+object
+-
+
+
+header 2.8+
+
+
+是否开启 Code 栏头部区域。
+
+
+boolean
+
+
+`false`
+
+
+
+
+ln
+
+
+是否显示 Code 区域的行号
+
+
+boolean
+
+
+`true`
+
+
+
+
+theme 2.8.17+
+
+
+Code 容器的主题风格,可选值有:
+
+- `light` 浅色模式(默认)
+- `dark` 深色模式
+
+
+string
+-
+
+
+encode
+
+
+是否对 code 中的 html 进行编码(转义)。
+
+
+boolean
+
+
+`true`
+
+
+
+
+lang 2.8.17+
+
+
+指定语言类型。如:`lang: 'html'`
+
+
+string
+-
+
+
+langMarker 2.8.17+
+
+
+是否在代码区域右上角显示语言类型
+
+
+boolean
+
+
+`false`
+
+
+
+
+wordWrap 2.8.17+
+
+
+Code 文字是否自动换行
+
+
+boolean
+
+
+`true`
+
+
+
+
+highlighter 2.8.17+
+
+
+设置语法高亮器,可选值:
+
+- `hljs` : 指定 `highlight.js` 库
+- `prism` : 指定 `prism.js` 库
+- `shiki` : 指定 `shiki.js` 库
+
+注:对应的语法高亮器 JS 库和相关主题 CSS 需自主引入,该属性仅用于内部适配。
+
+
+string
+-
+
+
+
+
+[codeRender](#options.codeRender) 2.8+
+
+
+
+
+
+用于重新渲染 code,譬如代码高亮处理。
+
+
+```
+codeRender: function(code, opts){
+ // 此处以 highlight.js 为例
+ return hljs.highlight(code, {language: opts.lang}).value;
+}
+```
+
+code 组件语法高亮相关示例:
+
+- highlight 和 prism 语法高亮示例
+- shiki 语法高亮示例
+
+
+
+
+
+
+[done](#options.done) 2.8+
+
+
+
+
+
+组件渲染完毕的回调函数,函数返回一个 object 类型参数
+
+
+```
+done: function(obj){
+ var container = obj.container; // 当前面板的容器对象
+ obj.render(); // 对预览中的 `element,form` 等组件进行渲染
+}
+```
+
+
+
+
+
+
+[onCopy](#options.onCopy) 2.8.2+
+
+
+
+
+
+点击复制图标时的回调函数。
+
+
+```
+onCopy: function(code, copied){
+ console.log(code); // 得到当前 code 内容
+ console.log(copied); // 是否复制成功(2.9.21+)
+
+ return false; // 返回 false 阻止内置提示(2.9.21+)
+}
+
+```
+
+
+
+
+
+
+[highlightLine](#options.highlightLine) 2.12+
+
+
+
+
+
+
+设置行高亮,可选项:
+- `hl` : 高亮
+- `++` : diff++
+- `--` : diff--
+- `focus` : 聚焦
+
+
+
+可通过 `hl.range` 选项来设置行高亮范围:
+
+```
+highlightLine: {
+ hl: {
+ range: '1,3-5,8', // 指定行高亮范围 '1,3,4,5,8'
+ comment: true, // 是否解析行中的高亮注释
+ }
+}
+```
+
+或通过特定注释格式: `[!code :]` 指定行高亮范围,规则解释:
+- `` : `highlightLine` 的可选项,如 `h1, focus` 等
+- `` : 行数(含本行)
+
+```
+111 聚焦 2 行(含本行) // [!code focus:2]
+222 高亮本行 // [!code hl]
+333
+```
+
+highlightLine 选项的详细用法可参考:highlightLine 行高亮在线示例
+
+
+
+
+
+
diff --git a/docs/code/index.md b/docs/code/index.md
new file mode 100644
index 000000000..87d4500c2
--- /dev/null
+++ b/docs/code/index.md
@@ -0,0 +1,66 @@
+---
+title: Code 预览组件 code
+toc: true
+---
+
+# Code 预览组件
+
+> 代码预览组件 `code` 主要用于对代码区块的修饰和对应的效果预览,如 Layui 各组件文档中的示例演示。
+
+
+方法
+
+`var codeInst = layui.code(options);`
+
+- 参数 `options` : 基础属性选项。[#详见属性](#options)。
+
+其中 `codeInst` 即实例返回的对象,包含对当前实例进行重载等方法成员,如:
+
+```
+var codeInst = layui.code(options);
+console.log(codeInst); // 查看所有成员
+codeInst.config; // 当前实例配置项
+codeInst.reload(options); // 重载
+```
+
+
+另外,属性除了在该方法中传递,也可以直接写在元素的 `lay-options` 属性上,如:
+
+
+
+
+
+属性
+
+
+{{- d.include("/code/detail/options.md") }}
+
+
+小贴士
+
+> code 组件可广泛应用于技术类文档、博客等页面,可轻松适配第三方主流语法高亮器。
+
diff --git a/docs/color/index.md b/docs/color/index.md
new file mode 100644
index 000000000..66f218a4c
--- /dev/null
+++ b/docs/color/index.md
@@ -0,0 +1,140 @@
+---
+title: 颜色
+toc: true
+---
+
+# 颜色
+
+> Layui 试图在清新与深沉之间寻求某种柔和,以不过分刺激大脑皮层的神经介质,反馈出经久耐看的微妙视图。您可以在我们精心调配的如下色系中合理搭配,减少不必要的违和感,从而使您的 Web 页面看上去尽可能融洽。
+
+基色调
+
+
+
+Layui 选取以象征清新与包容的「蓝绿色」作为主色调,它介于蓝与绿之间,亦可称之为「青色」,所谓青者,取之于蓝而深于绿,此间包罗万象,跨越时空。这也是我们对技术创作与人生哲学之间的一点思考。
+
+
+辅色调
+
+
+
+
+
#ff5722
+
错误 - Danger
+
+
+
+
+
#ffb800
+
警示 - Warning
+
+
+
+
+
+
#16b777
+
成功 - Success
+
+
+
+
+
+页面中同样也少不了辅助色彩的点缀,以对不同含义的内容加以区分。Layui 从暖色系(红/橙)和冷色系(绿/蓝)中,各自调取了我们认为最具代表性的颜色值,它们通常在不同的场景中发挥着不同的作用。
+
+中色调
+
+
+
+中性的颜色是页面中的重要组成部分,也被称之为无彩色系,一般用于文本、背景和边框等。它能对由彩色进行视觉冲淡,以达到和谐自然的效果。Layui 认为恰当的灰度调配代表着极简,这是一种神奇的色系,是视觉疲劳的栖息,低调而优雅,且永不过时。
+
+七色调
+
+
+
+ #ff5722 - 红
+
+
+ #ffb800 - 橙
+
+
+ #16baaa - 绿
+
+
+ #1e9fff - 蓝
+
+
+ #a233c6 - 紫
+
+
+ #2f363c - 深
+
+
+ #fafafa - 浅
+
+
+
+Layui 的色调基础,除了前面提到的主辅中色之外,还建立在以上罗列的七种颜色之上。你同样也可以遵循我们提供的色调方案去扩展你的页面元素,使得能与 Layui 的主题风格无缝融合。
+
+
+
+## 标语
+
+> 不热衷于视觉设计的开发者不是一个好作家。 —— 贤心
+
diff --git a/docs/colorpicker/detail/demo.md b/docs/colorpicker/detail/demo.md
new file mode 100644
index 000000000..81e21bc3f
--- /dev/null
+++ b/docs/colorpicker/detail/demo.md
@@ -0,0 +1,256 @@
+
+
+
+
+
+
+
+
+
+
+设置 RGB / RGBA
+
+
+
+
+
+
+
+
+
+
+
+开启透明度
+
+
+
+
+
+
+
+
+
+
+
+
+预定义颜色项
+
+
+
+
+
+
+
+
+
+
+
+全功能和回调的使用
+
+
+
+主题按钮
+
+
+演示:选择颜色并确定,改变上方按钮背景色
+
+
+
+
+
+
+颜色框尺寸
+
+
+
+
+
+
+
+
+
+
+
+
+同时绑定多个元素
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/colorpicker/detail/options.md b/docs/colorpicker/detail/options.md
new file mode 100644
index 000000000..510a2ccd7
--- /dev/null
+++ b/docs/colorpicker/detail/options.md
@@ -0,0 +1,178 @@
+
+
+
+
+
+
+
+
+
+ 属性名
+ 描述
+ 类型
+ 默认值
+
+
+
+
+elem
+
+
+绑定元素选择器或 DOM 对象
+
+
+string/DOM
+-
+
+
+color
+
+
+默认颜色值,值的格式跟随 `format` 属性的设定。
+
+
+string
+-
+
+
+format
+
+
+颜色显示/输入格式,支持 `hex` `rgb` 。 若同时开启 `alpha` 属性,则颜色值自动变为 `rgba`。
+
+
+string
+
+
+`hex`
+
+
+
+
+alpha
+
+
+是否开启透明度。当同时开启 `format: 'rgb'` 时,`color` 值将采用 `rgba` 格式。
+
+
+boolean
+
+
+`false`
+
+
+
+
+predefine
+
+
+是否开启预定义颜色栏
+
+
+boolean
+
+
+`false`
+
+
+
+
+colors
+
+
+设置可选的颜色列表,需开启 `predefine: true` 有效。
+ 用法详见:[#预定义颜色项](#demo-predefine)
+
+
+array
+-
+
+
+size
+
+
+颜色框的尺寸,可选值: `lg` `sm` `xs`
+
+
+string
+
+
+`sm`
+
+
+
+
+
+
+
+
+
+[回调函数](#options.callback)
+
+
+
+
+
+
+change
+
+
+颜色被改变的回调函数。用法详见:[#示例](#demo-all)
+
+```
+change: function(value){
+ console.log(value); // 当前颜色值
+}
+```
+
+
+
+
+done
+
+
+颜色选择完毕的回调函数。点击“确认”和“清除”按钮均会触发
+
+```
+done: function(value){
+ console.log(value); // 当前选中的颜色值
+}
+```
+
+用法详见:[#示例](#demo-all)
+
+
+
+
+cancel 2.8+
+
+
+取消颜色选择的回调函数,一般点击非颜色选择面板区域触发。
+
+```
+cancel: function(value){
+ console.log(value); // 当前颜色值
+}
+```
+
+用法详见:[#示例](#demo-all)
+
+
+
+
+close 2.8+
+
+
+颜色选择面板被关闭后即触发。
+
+```
+close: function(value){
+ console.log(value); // 当前颜色值
+}
+```
+
+
+
+
+
+
diff --git a/docs/colorpicker/index.md b/docs/colorpicker/index.md
new file mode 100644
index 000000000..fdff02d46
--- /dev/null
+++ b/docs/colorpicker/index.md
@@ -0,0 +1,63 @@
+---
+title: 颜色选择器 colorpicker
+toc: true
+---
+
+# 颜色选择器
+
+> 颜色选择器 `colorpicker` 用于对颜色的快捷选择,支持 `hex,rgb,rgba` 三种颜色类型。
+
+示例
+
+
+{{- d.include("/colorpicker/detail/demo.md") }}
+
+
+
+
+API
+
+| API | 描述 |
+| --- | --- |
+| var colorpicker = layui.colorpicker | 获得 `colorpicker` 模块。 |
+| [基础接口](../component/#export) 2.13+ | 该组件由 `component` 构建,因此继承其提供的基础接口。|
+| [colorpicker.render(options)](#render) | colorpicker 组件渲染,核心方法。 |
+
+
+渲染
+
+`colorpicker.render(options);`
+
+- 参数 `options` : 基础属性选项。[#详见属性](#options)
+ 注 2.7+ : 除 `elem` 属性外,其他基础属性也可以直接写在元素的 `lay-options="{}"` 属性中。
+
+```
+
+
+
+
+
+
+```
+
+属性
+
+
+{{- d.include("/colorpicker/detail/options.md") }}
+
+
+## 兼容性
+
+> colorpicker 组件支持 `Chrome,Edge,Firefox` 等所有高级浏览器,不支持 IE10 低版本浏览器。
diff --git a/docs/component/detail/options.md b/docs/component/detail/options.md
new file mode 100644
index 000000000..f6a32d1a4
--- /dev/null
+++ b/docs/component/detail/options.md
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+ 属性名
+ 描述
+ 类型
+ 默认值
+
+
+
+
+name
+
+
+组件名称。如 `name:'tabs'`,在使用组件时,即可通过 `layui.tabs` 获得该组件。注:*组件名必须唯一*。
+
+
+string
+-
+
+
+config
+
+
+定义组件渲染时的默认配置项。
+
+
+object
+-
+
+
+CONST
+
+
+通用常量集,一般存放固定字符,如类名等。如:
+
+```
+CONST: {
+ ELEM: 'lay-tabs',
+}
+```
+
+上述常量可通过 `component.CONST.ELEM` 获得。
+
+
+object
+-
+
+
+isDeepReload 实验性
+
+
+组件重载时是否允许深度重载,即对重载时选项进行深度合并。
+
+
+boolean
+
+
+`false`
+
+
+
+
+
+
+
+
+[回调函数](#options.callback)
+
+
+
+
+
+
+render
+
+
+组件渲染的逻辑。
+
+```js
+render: function() {
+ // 组件的容器构建、插入等
+ // …
+}
+```
+
+也可以通过原型 `component.Class.prototype.render` 进行定义。
+
+
+
+
+beforeInit
+
+
+组件初始化之前的回调函数。
+
+```js
+beforeInit: function(options) {
+ console.log(options); // 获得组件初始化前的配置项
+}
+```
+
+
+
+
+beforeRender
+
+
+渲染之前的回调函数。
+
+```js
+beforeRender: function(options) {
+ console.log(options); // 获得组件渲染前的配置项
+}
+```
+
+
+
+
+extendsInstance
+
+
+扩展组件渲染的实例对象的回调函数。如:
+
+```js
+extendsInstance: function(that) {
+ return {
+ // 关闭组件
+ close: function() {
+ that.remove(); // 调用组件原型中的 remove 方法
+ }
+ }
+}
+```
+
+当组件渲染时,即可通过它返回的对象调用实例方法:
+
+```js
+var inst = xxx.render(); // 某组件渲染
+inst.close(); // 关闭某组件
+```
+
+
+
+
+events
+
+
+定义组件各内部事件。
+
+```js
+events: function() {
+ // 亦可包含针对组件的 window, document 等全局事件
+ // …
+}
+```
+
+也可以通过原型 `component.Class.prototype.events` 进行定义。
+
+
+
+
+
+
diff --git a/docs/component/index.md b/docs/component/index.md
new file mode 100644
index 000000000..7edcbff1d
--- /dev/null
+++ b/docs/component/index.md
@@ -0,0 +1,304 @@
+---
+title: 组件构建器 component
+toc: true
+---
+
+# 组件构建器 2.10+
+
+> 组件构建器 `component` 是 2.10 版本新增的重要模块,旨在为 Layui 2 系列版本逐步构建统一 API 规范的组件。
+
+API
+
+| API | 描述 |
+| --- | --- |
+| [layui.component(options)](#create) | 创建组件 |
+
+创建组件
+
+`layui.component(options);`
+
+- 参数 `options` : 基础属性选项。[#详见属性](#options)
+
+该方法返回一个对象,包含用于组件对外的基础接口,如:组件渲染、重载、事件操作,及构造函数等等。用法示例:
+
+```js
+/**
+ * tabs
+ * 标签页组件
+ */
+layui.define('component', function(exports) {
+ // 创建组件
+ var component = layui.component({
+ name: 'tabs', // 组件名称
+ config: { // 组件默认配置项
+ // …
+ },
+ render: function() { // 组件渲染逻辑
+ // …
+ },
+ // 其他选项
+ });
+
+ // 将创建组件时返回的 `component` 对象作为组件的接口输出
+ // 组件将继承通用的基础接口,如 render, reload, set 等方法
+ exports(component.CONST.MOD_NAME, component);
+});
+```
+
+属性选项
+
+
+{{- d.include("/component/detail/options.md") }}
+
+
+基础接口 🔥
+
+通过 `component` 模块创建的组件,均会继承内部定义的「基础对外接口」和「组件渲染的通用选项」。
+
+| 接口 | 描述 |
+| --- | --- |
+| [component.render(options)](#render) | 组件渲染 |
+| [component.reload(id, options)](#reload) | 组件重载 |
+| [component.set(options)](#set) | 设置组件渲染时的全局配置项 |
+| [component.on(\'event(filter)\', callback)](#on) | 组件的自定义事件 |
+| [component.getInst(id)](#getInst) | 获取组件指定的实例对象 |
+| [component.removeInst(id)](#removeInst) 2.10.2+ | 删除组件指定的实例对象 |
+| component.index | 获得组件的自增索引 |
+| component.config | 获得组件渲染时的全局配置项。一般通过 `set` 方法设置 |
+| component.cache | 获得组件的缓存数据集。如组件实例 ID 集 |
+| [component.CONST](#CONST) | 获得组件的通用常量集。如 `MOD_NAME` 等 |
+| [component.Class](#Class) | 获得组件的构造函数。一般用于扩展原型方法 |
+
+> 😊 注:上表中的 `component` 为组件的基础对象,实际使用时,请根据实组件名称进行替换。如 `tabs` 组件,对应的接口则为:`tabs.render(options)` `tabs.on('event(filter)', callback)` 等。
+
+组件渲染
+
+`component.render(options)`
+
+- 参数 `options` : 组件渲染的配置项。可继承的通用选项见下表:
+
+| 选项 | 描述 |
+| --- | --- |
+| elem | 组件渲染指定的目标元素选择器或 DOM 对象 |
+| id | 组件渲染的唯一实例 ID |
+| show | 是否初始即渲染组件。通常结合创建组件设定的 `isRenderOnEvent` 选项决定是否启用 |
+
+更多渲染时的选项则由各组件内部单独定义,具体可查阅各组件对应的文档。
+
+```js
+// 以 tabs 组件为例
+// 渲染
+tabs.render({
+ elem: '#id',
+ // …
+});
+```
+
+组件重载
+
+`component.reload(id, options)`
+
+- 参数 `id` : 组件实例 ID。
+- 参数 `options` : 组件重载的配置项。
+
+该方法可实现对组件的完整重载。部分组件通常还提供了「仅数据重载」,具体可参考各组件对应的文档。
+
+```js
+// 以 tabs 组件为例
+// 重载 tabs 组件实例
+tabs.reload('id', {
+ // …
+})
+```
+
+全局设置
+
+`component.set(options)`
+
+- 参数 `options` : 组件渲染的配置项。
+
+该方法用于全局设置组件渲染时的默认配置项,需在组件渲染之前执行。
+
+```js
+// 以 tabs 组件为例
+// 全局设置。后续所有渲染均会生效,除非对选项进行覆盖
+tabs.set({
+ trigger: 'mouseenter' // 默认的触发事件
+ // …
+});
+
+// 渲染实例 1
+tabs.render({ id: 'id1'}); // 继承全局设置
+
+// 渲染实例 2
+tabs.render({
+ id: 'id2',
+ trigger: 'click' // 覆盖全局的触发事件
+});
+```
+
+事件定义
+
+`component.on('event(id)', callback)`
+
+- 参数 `event(id)` : 是事件的特定结构。 `event` 为事件名,支持的事件见各组件列表。`id` 为组件的实例 ID。
+- 参数 `callback` : 事件回调函数。返回的参数由各组件内部单独定义。
+
+具体事件一般由组件内部单独定义,具体可查看各组件对应的文档。
+
+```js
+// 以 tabs 组件为例:
+// 组件渲染成功后的事件
+tabs.on('afterRender(id)', function(data) {
+ console.log(obj);
+});
+```
+
+获取实例
+
+`component.getInst(id)`
+
+- 参数 `id` : 组件的实例 ID。
+
+该方法可获取组件渲染时对应的实例,以调用组件内部的原型方法,一般用于在外部对组件进行扩展或重构。
+
+```js
+// 以 tabs 组件为例
+var tabInstance = tabs.getInst('id');
+// 调用内部的标签滚动方法
+tabInstance.roll();
+```
+
+删除实例 2.10.2+
+
+`component.removeInst(id)`
+
+- 参数 `id` : 组件的实例 ID。
+
+该方法可删除组件渲染时对应的实例,*一般在完全移除组件时使用,否则可能造成组件相关方法失效*。
+
+```js
+// 以 tabs 组件为例
+tabs.removeInst('id');
+```
+
+基础常量
+
+`component.CONST`
+
+获取组件的通用常量集,一般存放固定字符,如类名等。
+
+```js
+// 基础常量如下
+component.CONST.MOD_NAME; // 组件名称
+component.CONST.MOD_INDEX; // 组件自增索引
+component.CONST.CLASS_THIS; // lay-this
+component.CONST.CLASS_SHOW; // lay-show
+component.CONST.CLASS_HIDE; // lay-hide
+component.CONST.CLASS_HIDEV; // lay-hide-v
+component.CONST.CLASS_DISABLED; // lay-disabled
+component.CONST.CLASS_NONE; // lay-none
+
+// 更多常量一般在各组件内部单独定义,以 tabs 组件为例
+tabs.CONST.ELEM; // lay-tabs
+```
+
+扩展接口
+
+除上述「基础接口」外,你也可以对接口进行任意扩展,如:
+
+```js
+/**
+ * 定义组件
+ */
+layui.define('component', function(exports) {
+ // 创建组件
+ var component = layui.component({
+ name: 'test',
+ // …
+ });
+ // 扩展组件接口
+ layui.$.extend(component, {
+ // 以扩展一个关闭组件面板的接口为例
+ close: function(id) {
+ var that = component.getInst(id);
+ if(!that) return this;
+ that.remove(obj); // 调用原型中的 remove 方法
+ }
+ });
+ // 输出组件接口
+ exports(component.CONST.MOD_NAME, component);
+});
+```
+
+```js
+/**
+ * 使用组件(以上述定义的 test 组件为例)
+ */
+layui.use('test', function() {
+ var test = layui.test;
+ // 渲染组件
+ test.render({
+ elem: '#id',
+ id: 'test-1'
+ });
+ // 关闭组件面板(通常在某个事件中使用)
+ test.close('test-1');
+});
+```
+
+扩展原型
+
+`component.Class`
+
+当通过 `layui.component()` 方法创建一个新的组件时,通常需借助 `Class` 构造函数扩展组件原型,以灵活实现组件的个性化定制。但一般不推荐重写 `component.js` 原型中已经定义的基础方法,如:`init, reload, cache`
+
+```
+/**
+ * 定义组件
+ */
+layui.define('component', function(exports) {
+ // 创建组件
+ var component = layui.component({
+ name: '', // 组件名称
+ // …
+ });
+
+ // 获取构造器
+ var Class = component.Class;
+
+ // 扩展原型
+ Class.prototype.xxx = function() {
+ // …
+ };
+ Class.prototype.aaa = function() {
+ // …
+ };
+
+ // 输出组件接口
+ exports(component.CONST.MOD_NAME, component);
+});
+```
+
+通过 `Class` 构造函数也可以对某个组件的原型进行重构,但一般不推荐,因为这可能破坏组件的基础功能。
+
+```
+// 以 tabs 组件为例
+var tabs = layui.tabs;
+
+// 获得 tabs 组件构造函数
+var Class = tabs.Class;
+
+// 重构 tabs 组件内部的 xxx 方法(不推荐)
+Class.prototype.xxx = function() {
+ // …
+};
+```
+
+您也可以直接参考 tabs 组件源码中关于扩展原型的具体实践。
+
+## 💖 心语
+
+一直以来,Layui 的很多组件自成一体,使得无法对组件进行较好的统一管理。尽管我们也曾努力尝试改善这个问题,但很多时候为了向下兼容而又不得不保留许多旧有的特性,随着组件的增加,该问题也显得越加明显。而 component 模块的出现,将在一定程度上填补这一缺憾,它的初衷正是为了确保 Layui 组件的一致性,如核心逻辑和 API 设计等,主要意义在于:**给 Layui 2 系列版本提供一个构建通用组件的方式**,增强其「生命力」。
+
+
diff --git a/docs/dropdown/detail/demo.md b/docs/dropdown/detail/demo.md
new file mode 100644
index 000000000..4afcb6184
--- /dev/null
+++ b/docs/dropdown/detail/demo.md
@@ -0,0 +1,57 @@
+基础用法
+
+
+
+{{- d.include("/dropdown/examples/base.md") }}
+
+
+
+复杂结构
+
+
+
+{{- d.include("/dropdown/examples/complex.md") }}
+
+
+
+在表格中应用
+
+
+
+{{- d.include("/dropdown/examples/table.md") }}
+
+
+
+自定义事件
+
+
+
+{{- d.include("/dropdown/examples/on.md") }}
+
+
+
+
+
+
+
+{{- d.include("/dropdown/examples/contextmenu.md") }}
+
+
+
+水平对齐方式
+
+
+
+{{- d.include("/dropdown/examples/align.md") }}
+
+
+
+自定义内容
+
+如下以弹出一个 `tab` 为例
+
+
+
+{{- d.include("/dropdown/examples/content.md") }}
+
+
diff --git a/docs/dropdown/detail/options.data.md b/docs/dropdown/detail/options.data.md
new file mode 100644
index 000000000..4e48b5fa0
--- /dev/null
+++ b/docs/dropdown/detail/options.data.md
@@ -0,0 +1,116 @@
+
+
+
+
+
+
+
+
+
+ 属性名
+ 描述
+ 类型
+ 默认值
+
+
+
+
+title
+
+
+菜单标题
+
+
+string
+-
+
+
+id
+
+
+菜单 ID。用户菜单项唯一索引
+
+
+
+number/string
+-
+
+
+type
+
+
+菜单项的类型,支持的可选值如下:
+
+- `normal` 普通菜单项(默认)
+- `group` 纵向组合收缩菜单
+- `parent` 横向父级菜单
+- `-` 分割线
+
+
+string
+
+
+`normal`
+
+
+
+
+href
+
+
+菜单项的 url 地址。若填写,点击菜单将直接发生跳转。
+
+
+string
+-
+
+
+target
+
+
+菜单 url 打开方式,需设置 `href` 属性后才生效。 一般可设为 `_blank` 或 `_self` 等
+
+
+string
+
+
+`_self`
+
+
+
+
+disabled 2.8+
+
+
+菜单项是否禁用状态
+
+
+boolean
+
+
+`false`
+
+
+
+
+templet
+
+
+自定义当前菜单项模板,优先级高于基础属性 `templet`
+
+
+string/function
+-
+
+
+child
+
+
+子级菜单数据集合。参数同父级,可无限嵌套。
+
+
+array
+-
+
+
+
diff --git a/docs/dropdown/detail/options.md b/docs/dropdown/detail/options.md
new file mode 100644
index 000000000..27f3c24e0
--- /dev/null
+++ b/docs/dropdown/detail/options.md
@@ -0,0 +1,354 @@
+
+
+
+
+
+
+
+
+
+ 属性名
+ 描述
+ 类型
+ 默认值
+
+
+
+
+elem
+
+
+绑定元素选择器或 DOM 对象
+
+
+string/DOM
+-
+
+
+
+
+[data](#options.data)
+
+
+
+
+下拉菜单的数据源。格式详见:[#data 格式](#options.data)
+
+
+array
+-
+
+
+ id
+
+
+设定实例唯一索引,以便用于其他方法对例进行相关操作。若该属性未设置,则默认从 `elem` 属性绑定的元素中的 `id` 属性值中获取。
+
+
+string
+-
+
+
+trigger
+
+
+触发组件的事件类型。支持所有事件,如: `click,hover,mousedown,contextmenu` 等
+
+
+string
+
+
+`click`
+
+
+
+
+closeOnClick 2.9.18+
+
+
+下拉面板打开后,再次点击目标元素时是否关闭该面板。
+
+
+boolean
+
+
+`true`
+
+
+
+
+show
+
+
+是否渲染即显示组件面板。该属性一般在重载方法中传递。
+
+
+boolean
+
+
+`false`
+
+
+
+
+align
+
+
+下拉面板相对绑定元素的水平对齐方式。支持以下可选值:
+
+- `left` 左对齐(默认)
+- `center` 居中对齐
+- `right` 右对齐
+
+
+string
+
+
+`left`
+
+
+
+
+isAllowSpread
+
+
+是否允许菜单组展开收缩
+
+
+boolean
+
+
+`true`
+
+
+
+
+isSpreadItem
+
+
+是否初始展开子菜单
+
+
+boolean
+
+
+`true`
+
+
+
+
+accordion 2.8.18+
+
+
+是否开启手风琴效果
+
+
+boolean
+
+
+`false`
+
+
+
+
+delay
+
+
+延迟触发的毫秒数。当 `trigger: 'hover'` 时才生效。示例:
+
+- `delay: 300` : 表示显示与隐藏的延迟时间均为 300 毫秒
+- `delay: [200, 300]` 2.9.2+ : 数组成员值分别表示显示延迟时间和隐藏延迟时间
+
+
+number/array
+
+
+`[200, 300]`
+
+
+
+
+className
+
+
+自定义组件主容器的样式类名,从而在外部重新定义样式。
+
+
+string
+-
+
+
+style
+
+
+设置组件主容器的 `CSS` 样式。
+
+
+string
+-
+
+
+shade 2.8+
+
+
+设置弹出时的遮罩。支持以下方式赋值:
+
+- 若值为 `number` 类型,则表示为遮罩透明度,如:
+ `shade: 0.3`
+- 若值为 `array` 类型,则可同时设置透明度和背景色,如:
+ `shade: [0.3, '#000']`
+
+
+number array
+
+
+`0`
+
+
+
+
+templet
+
+
+全局定义菜单的列表模板,可添加任意 `html` 字符,且支持 [laytpl](../laytpl/) 模板语法。用法详见:[#示例](#demo-complex)
+
+注 2.8+ : 模板亦可采用函数写法:
+
+```
+templet: function(d){
+ return '> ' + d.title;
+}
+```
+
+
+string function
+-
+
+
+content
+
+
+ 自定义组件内容,从而替代默认的菜单结构。用法详见:[#示例](#demo-content)
+
+
+string
+-
+
+
+clickScope 2.8+
+
+
+设置触发点击事件的菜单范围。 支持以下可选值:
+
+- `all` : 即代表父子菜单均可触发事件
+
+默认无需设置,即父级菜单不触发事件
+
+
+string
+-
+
+
+
+
+[customName](#options.customName) 2.8.14+
+
+
+
+
+自定义 `data` 数据源中常用的字段名称。
+
+
+object
+-
+
+
+
+
+
+
+
+[回调函数](#options.callback)
+
+
+
+
+
+
+ready
+
+
+组件成功弹出后的回调函数。返回的参数如下:
+
+```
+ready: function(elemPanel, elem){
+ console.log(elemPanel); // 组件面板元素对象
+ console.log(elem); // 当前组件绑定的目标元素对象
+}
+```
+
+
+
+
+
+
+[click](#options.click)
+
+
+
+
+
+菜单项被点击时的回调函数。返回的参数如下:
+
+
+```
+click: function(data, othis, event){
+ console.log(data); // 当前所点击的菜单项对应的数据
+ console.log(othis); // 当前所点击的菜单项元素对象
+ console.log(this.elem); // 当前组件绑定的目标元素对象,批量绑定中常用
+ console.log(event); // 事件对象 2.9.18+
+
+ // 若返回 false,则点击选项可不关闭面板 --- 2.8+
+ /*
+ return false;
+ */
+}
+```
+
+用法详见:[#示例](#examples)
+
+
+
+
+close 2.9.7+
+
+
+面板关闭后的回调函数。返回的参数如下:
+
+```
+close: function(elem){
+ console.log(elem); // 当前组件绑定的目标元素对象
+}
+```
+
+
+
+
+onClickOutside 2.9.18+
+
+
+点击 dropdown 外部时的回调函数,返回 `false` 可阻止关闭。
+
+```
+onClickOutside: function(event){
+ // 参数 event 即为当前点击的事件对象
+ // …
+ // return false; // 若返回 false,当点击面板外部时可阻止关闭
+}
+```
+
+
+
+
+
+
diff --git a/docs/dropdown/examples/align.md b/docs/dropdown/examples/align.md
new file mode 100644
index 000000000..6ed7efe5c
--- /dev/null
+++ b/docs/dropdown/examples/align.md
@@ -0,0 +1,38 @@
+
+
+ 左对齐
+
+
+
+ 居中对齐
+
+
+
+ 右对齐
+
+
+
+
+
+
diff --git a/docs/dropdown/examples/base.md b/docs/dropdown/examples/base.md
new file mode 100644
index 000000000..7451cdc27
--- /dev/null
+++ b/docs/dropdown/examples/base.md
@@ -0,0 +1,123 @@
+
+
+ 下拉菜单
+
+
+
+ 下拉菜单
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/dropdown/examples/complex.md b/docs/dropdown/examples/complex.md
new file mode 100644
index 000000000..a51f47262
--- /dev/null
+++ b/docs/dropdown/examples/complex.md
@@ -0,0 +1,129 @@
+
+ 无限层级 + 跳转 + 事件 + 自定义模板
+
+
+
+
diff --git a/docs/dropdown/examples/content.md b/docs/dropdown/examples/content.md
new file mode 100644
index 000000000..045517c99
--- /dev/null
+++ b/docs/dropdown/examples/content.md
@@ -0,0 +1,42 @@
+
+ 自定义内容
+
+
+
+
+
+
+
+
diff --git a/docs/dropdown/examples/contextmenu.md b/docs/dropdown/examples/contextmenu.md
new file mode 100644
index 000000000..64785df85
--- /dev/null
+++ b/docs/dropdown/examples/contextmenu.md
@@ -0,0 +1,92 @@
+
+
+
+ 开启全局右键菜单
+
+
+
+
+
diff --git a/docs/dropdown/examples/on.md b/docs/dropdown/examples/on.md
new file mode 100644
index 000000000..10f0b2625
--- /dev/null
+++ b/docs/dropdown/examples/on.md
@@ -0,0 +1,38 @@
+
+
+ hover
+
+
+
+ mousedown
+
+
+
+ dblclick - 双击
+
+
+
+
+
+
diff --git a/docs/dropdown/examples/reload.md b/docs/dropdown/examples/reload.md
new file mode 100644
index 000000000..ca6d8f42f
--- /dev/null
+++ b/docs/dropdown/examples/reload.md
@@ -0,0 +1,40 @@
+
+ 下拉菜单
+
+
+
+
+
diff --git a/docs/dropdown/examples/reloadData.md b/docs/dropdown/examples/reloadData.md
new file mode 100644
index 000000000..a307a899c
--- /dev/null
+++ b/docs/dropdown/examples/reloadData.md
@@ -0,0 +1,58 @@
+
+
+
+
diff --git a/docs/dropdown/examples/table.md b/docs/dropdown/examples/table.md
new file mode 100644
index 000000000..7dfc6f6d2
--- /dev/null
+++ b/docs/dropdown/examples/table.md
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
diff --git a/docs/dropdown/index.md b/docs/dropdown/index.md
new file mode 100644
index 000000000..db056ba74
--- /dev/null
+++ b/docs/dropdown/index.md
@@ -0,0 +1,181 @@
+---
+title: 下拉菜单 dropdown
+toc: true
+---
+
+# 下拉菜单 2.6+
+
+> 下拉菜单 `dropdown` 是基于基础菜单结构衍生的多功能通用下拉菜单组件,它将原本静态呈现的菜单,通过各种事件的形式触发,从而以独立面板的形式弹出。不仅可用作常见的*下拉菜单*,更可用于*右键菜单*来实现更多的交互可能。
+
+示例
+
+
+{{- d.include("/dropdown/detail/demo.md") }}
+
+
+在 `content` 属性中传入任意的 html 内容,可替代默认的下拉菜单结构,从而实现更丰富的弹出内容。
+
+API
+
+| API | 描述 |
+| --- | --- |
+| var dropdown = layui.dropdown | 获得 `dropdown` 模块。 |
+| [dropdown.render(options)](#render) | dropdown 组件渲染,核心方法。 |
+| [dropdown.reload(id, options)](#reload) | 完整重载 |
+| [dropdown.reloadData(id, options)](#reload) 2.8+ | 仅重载数据或内容 |
+| [dropdown.close(id)](#close) | 关闭对应的组件面板 |
+| [dropdown.open(id)](#open) 2.9.8+ | 打开对应的组件面板 |
+
+渲染
+
+`dropdown.render(options);`
+
+- 参数 `options` : 基础属性选项。[#详见属性](#options)
+ 注 2.8+ : 除 `elem` 属性外,其他基础属性也可以直接写在元素的 `lay-options="{}"` 属性中。
+
+```
+下拉菜单
+下拉菜单
+下拉菜单
+
+
+
+```
+
+属性
+
+
+{{- d.include("/dropdown/detail/options.md") }}
+
+
+data 格式
+
+
+{{- d.include("/dropdown/detail/options.data.md") }}
+
+
+
+
+您可以对上述 `data` 中常用的字段进行自定义名称 2.8.14+ :
+
+
+
+```
+var dropdown = layui.dropdown;
+// 渲染
+dropdown.render({
+ elem: '', // 绑定元素选择器
+ data: [], // 数据源
+ customName: { // 自定义 data 字段名 --- 2.8.14+
+ id: 'id',
+ title: 'title',
+ children: 'child'
+ },
+ // 其他属性 …
+});
+```
+
+
+重载
+
+即对一段已经渲染好的下拉菜单重新设置相关属性并渲染,可分为以下几种重载方式:
+
+| 重载方式 | API |
+| --- | --- |
+| [完整重载](#dropdown.reload) | [dropdown.reload(id, options, deep)](#dropdown.reload) |
+| [仅数据或内容重载](#dropdown.reloadData) 2.8+ | [dropdown.reloadData(id, options, deep)](#dropdown.reloadData) |
+
+
+两者重载的使用方式完全相同,区别只是在于参与重载时的属性差异及其对应的效果差异。一般按照实际需求选择使用。
+
+完整重载
+
+`dropdown.reload(id, options);`
+
+- 参数 `id` : 组件渲染时定义的 `id` 属性值
+- 参数 `options` : 基础属性选项。[#详见属性](#options)
+
+该方法用于对下拉菜单进行完整重载,所有属性均可参与到重载中。
+
+
+
+{{- d.include("/dropdown/examples/reload.md") }}
+
+
+
+仅数据或内容重载 2.8+
+
+`dropdown.reloadData(id, options);`
+
+- 参数同 `dropdown.reload(id, options)` 参数
+
+使用该方法时,与数据无关的属性不会参与到重载中。因此若只是更新数据或内容,该方法可大幅提升体验。
+
+
+
+{{- d.include("/dropdown/examples/reloadData.md") }}
+
+
+
+
+关闭面板 2.8+
+
+`dropdown.close(id);`
+
+- 参数 `id` : 组件渲染时定义的 `id` 属性值
+
+该方法用于关闭对应的 `dropdown` 组件面板。
+
+```
+var dropdown = layui.dropdown;
+
+// 渲染
+dropdown.render({
+ elem: '', // 绑定元素选择器
+ id: 'test', // 自定义 id
+ // 其他属性 …
+});
+// 关闭对应的组件面板
+dropdown.close('test');
+```
+
+
+打开面板 2.9.8+
+
+`dropdown.open(id);`
+
+- 参数 `id` : 组件渲染时定义的 `id` 属性值
+
+该方法用于打开对应的 `dropdown` 组件面板。
+
+```
+var dropdown = layui.dropdown;
+
+// 渲染
+dropdown.render({
+ elem: '', // 绑定元素选择器
+ id: 'test', // 自定义 id
+ // 其他属性 …
+});
+// 打开对应的组件面板
+dropdown.open('test');
+```
+
diff --git a/docs/favicon.ico b/docs/favicon.ico
new file mode 100644
index 000000000..5457e78a1
Binary files /dev/null and b/docs/favicon.ico differ
diff --git a/docs/fixbar/detail/demo.md b/docs/fixbar/detail/demo.md
new file mode 100644
index 000000000..3cf1aaa22
--- /dev/null
+++ b/docs/fixbar/detail/demo.md
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+ 自定义固定条示例 - Layui
+
+
+
+
+
+
+
+ 页 面 内 容 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。
+
+
+
+
+
+
+
+
+
diff --git a/docs/fixbar/detail/options.md b/docs/fixbar/detail/options.md
new file mode 100644
index 000000000..7c08fa338
--- /dev/null
+++ b/docs/fixbar/detail/options.md
@@ -0,0 +1,171 @@
+
+
+
+
+
+
+
+
+
+ 属性名
+ 描述
+ 类型
+ 默认值
+
+
+
+
+bars 2.8+
+
+
+设置固定工具条列表。可支持定义以下子属性:
+
+```
+bars: [
+ {
+ type: '', // bar 类型名,用于事件区分
+ icon: '', // bar 图标的 className
+ content: '', // bar 任意内容
+ style: '' // bar 任意样式
+ },
+ // …
+]
+```
+
+该属性比较灵活,具体用法可参考:[#示例](#examples)
+
+
+array
+
+
+查看默认值
+
+
+
+
+default 2.8+
+
+
+是否显示默认的固定条 ,如 `top` (点击可让滚动条置顶)等
+
+
+boolean
+
+
+`true`
+
+
+
+
+bgcolor
+
+
+固定条的默认背景色
+
+
+string
+-
+
+
+css
+
+
+工具条外层容器的任意 css 属性。如设置工具条的坐标:
+
+```
+css: {right: 32, bottom: 32}
+```
+
+
+object
+-
+
+
+target 2.8+
+
+
+插入固定条的目标元素选择器
+
+
+object
+
+
+`body`
+
+
+
+
+scroll 2.8+
+
+
+固定条最外层容器滚动条所在的元素,若不设置则默认取 `target` 属性值
+
+
+object
+
+
+`body`
+
+
+
+
+margin 2.8+
+
+
+用于设置默认 `TOP` 条出现滚动条的高度临界值
+
+
+number
+
+
+`200`
+
+
+
+
+duration 2.8+
+
+
+用于默认 `TOP` 条等动画时长
+
+
+number
+
+
+`200`
+
+
+
+
+on 2.8+
+
+
+用于定义固定条列表的任意事件,触发事件时的回调将返回 `bars` 属性的 `type` 值。
+
+```
+on: {
+ // 点击事件
+ click: function(type){
+ // bars 对属性应的 type 值
+ console.log(type);
+ },
+ // …
+}
+```
+
+该属性一般与 `bars` 属性搭配使用,具体用法可参考:[#示例](#examples)
+
+
+object
+-
+
+
+
+
+
+### 贴士
+
+> 灵活运用 `bars` 属性的 `content,style` 子属性,可实现更多丰富多样的固定条。
diff --git a/docs/fixbar/index.md b/docs/fixbar/index.md
new file mode 100644
index 000000000..5f458c70e
--- /dev/null
+++ b/docs/fixbar/index.md
@@ -0,0 +1,33 @@
+---
+title: 固定条组件 fixbar
+toc: true
+---
+
+# 固定条组件
+
+> 固定条组件 `fixbar` 是指当滚动条滑动时,始终固定在页面一侧的工具条元素,除了内置的 `TOP` 条功能外,还可以灵活地扩展任意自定义的工具条。在 `2.x` 版本中,`fixbar` 属于 `util` 模块的子集。
+
+示例
+
+
+{{- d.include("/fixbar/detail/demo.md") }}
+
+
+API
+
+| API | 描述 |
+| --- | --- |
+| var util = layui.util | 获得 `util` 模块。 |
+| [util.fixbar(options)](#fixbar) | fixbar 组件渲染,核心方法。 |
+
+渲染
+
+`util.fixbar(options);`
+
+- 参数 `options` : 基础属性选项。[#详见属性](#options)
+
+属性
+
+
+{{- d.include("/fixbar/detail/options.md") }}
+
diff --git a/docs/flow/detail/demo.md b/docs/flow/detail/demo.md
new file mode 100644
index 000000000..d26ab9cf8
--- /dev/null
+++ b/docs/flow/detail/demo.md
@@ -0,0 +1,65 @@
+滚动加载
+
+
+
+
+
+
+
+
+
+
+手动加载
+
+
+
+
+
+
+
+
+
diff --git a/docs/flow/detail/options.md b/docs/flow/detail/options.md
new file mode 100644
index 000000000..651a632f0
--- /dev/null
+++ b/docs/flow/detail/options.md
@@ -0,0 +1,155 @@
+
+
+
+
+
+
+
+
+
+ 属性名
+ 描述
+ 类型
+ 默认值
+
+
+
+
+elem
+
+
+绑定元素选择器或 DOM 对象
+
+
+string
+-
+
+
+scrollElem
+
+
+指定触发流加载的滚动条所在元素选择器。
+
+
+string
+
+
+`document`
+
+
+
+
+isAuto
+
+
+是否自动加载。 若设为 `false`,则会在列表底部生成一个「加载更多」的按钮,那么可点击该按钮加载下一页数据。
+
+
+boolean
+
+
+`true`
+
+
+
+
+moreText 2.9.11+
+
+
+设置「加载更多」按钮的文本
+
+
+string
+
+
+加载更多
+
+
+
+
+end
+
+
+设置加载完毕后的最尾部的内容,可传入任意 HTML 字符。
+
+
+string
+
+
+没有更多了
+
+
+
+
+isLazyimg
+
+
+是否开启信息流中的图片懒加载。若设为 `true` ,则只会对在可视区域的图片进行按需加载。但同时,在拼接列表字符的时候,您不能给列表中的 ` ` 标签赋值 `src`,必须要用 `lay-src` 属性取代,如:
+
+```
+data.forEach(function(item){
+ lis.push(' ');
+});
+```
+
+
+boolean
+
+
+`false`
+
+
+
+
+mb
+
+
+与底部的临界距离。 即当滚动条与底部产生该距离时,触发加载。 必须 `isAuto:true` 时有效。
+
+*小贴士*: 此处 `mb` 属性名是 css 中 `margin-bottom` 的简写,可并非国粹之语 😅
+
+
+number
+
+
+`50`
+
+
+
+
+direction 2.9.7+
+
+
+指定触发加载的方向,可选值:
+- `bottom` 滚动容器底部触发加载
+- `top` 滚动容器顶部触发加载
+
+
+string
+'bottom'
+
+
+done
+
+
+
+滚动条到达临界点触发加载的回调函数。函数返回的参数如下:
+
+
+```
+done: function(page, next){
+ console.log(page) // 获得当前页
+
+ // 执行下一页渲染,第二参数为:满足“加载更多”的条件,即后面仍有分页
+ // 只有当前页小于总页数的情况下,才会继续出现加载更多
+ next('列表 HTML 片段', page < res.pages);
+}
+```
+
+详细用法可参考:[#示例](#examples)
+
+
+
+
+
+
diff --git a/docs/flow/index.md b/docs/flow/index.md
new file mode 100644
index 000000000..2c8cebd90
--- /dev/null
+++ b/docs/flow/index.md
@@ -0,0 +1,94 @@
+---
+title: 流加载 flow
+toc: true
+---
+
+# 流加载
+
+> 流加载 `flow` 是用于在*信息流*和*图片列表*场景中的滚动按需加载,对前后端的体验和性能优化具有一定帮助。
+
+示例
+
+
+
+
+{{- d.include("/flow/detail/demo.md") }}
+
+
+API
+
+| API | 描述 |
+| --- | --- |
+| var flow = layui.flow | 获得 `flow` 模块。 |
+| [基础接口](../component/#export) 2.13+ | 该组件由 `component` 构建,因此继承其提供的基础接口。|
+| [flow.load(options)](#load) | 信息流加载,核心方法。 |
+| [flow.lazyimg(options)](#lazyimg) | 图片懒加载。 |
+
+信息流
+
+`flow.load(options);`
+
+- 参数 `options` : 基础属性选项。[#详见属性](#options)
+
+信息流是分页的另一种表现形式,新加载的内容不替换原有的内容,而是随着滚动条滚动而追加显示。[#详见示例](#examples)
+
+属性
+
+
+{{- d.include("/flow/detail/options.md") }}
+
+
+图片懒加载
+
+`flow.lazyimg(options);`
+
+- 参数 `options` : 属性选项。可选项见下表。
+
+| 属性名 | 描述 |
+| --- | --- |
+| elem | 绑定容器中需进行懒加载的图片元素选择器 |
+| scrollElem | 滚动条所在元素选择器,默认 `document` 。 |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+无论滚动条上滑还是下滑,都会始终加载当前屏的图片。
+
+
diff --git a/docs/form/checkbox.md b/docs/form/checkbox.md
new file mode 100644
index 000000000..c20b3e17c
--- /dev/null
+++ b/docs/form/checkbox.md
@@ -0,0 +1,192 @@
+---
+title: 复选框
+toc: true
+---
+
+# 复选框
+
+> 复选框组件是对 ` ` 元素的美化替代,在原有的特性基础上,对 UI 进行了加强。
+
+
+默认风格
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+- 属性 `title` 可设置复选框标题
+- 属性 `checked` 可设置默认选中
+- 属性 `disabled` 可设置禁用状态
+- 属性 `value` 可设置值,否则选中时返回的默认值为 `on`(浏览器默认机制)
+- 属性 `lay-skin` 可设置复选框风格,可选值:`tag`2.8+ ,`switch`,`none`(无样式)2.9.8+ 默认风格可不填
+
+特别地,当表单提交时,只有选中状态的复选框才能获取到 `value`,这点和浏览器原有的复选框机制相同。
+
+注 2.8+ : `lay-skin` 属性在之前版本默认为标签风格,新版本调整为默认原始风格(`lay-skin="primary"`)。
+
+标签风格
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+开关风格
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+在 `title` 属性中通过 `|` 分隔符可设置两种状态下的不同标题
+
+
+自定义标题模板 2.8.3+
+
+在 `checkbox` 元素后的相邻元素设置特定属性 `lay-checkbox`,可以与 `checkbox` 标题进行绑定。
+
+
+
+
+
+
+
+
+
+自定义任意风格 2.9.8+
+
+通过对 `checkbox` 元素设置 `lay-skin="none"` 属性禁用默认样式,从而实现任意风格的多选组件。
+**注:** 这意味着你需要掌握一定的 `CSS` 技能,以下示例中的样式均为外部自主实现,并非 Layui 内置。
+
+
+
+{{- d.include("/form/examples/checkbox.skin.md") }}
+
+
+
+
+复选框事件
+
+| 风格 | 事件 |
+| --- | --- |
+| 默认风格 / 标签风格 | `form.on('checkbox(filter)', callback);` |
+| 开关风格 | `form.on('switch(filter)', callback);` |
+
+- `checkbox` 和 `switch` 为复选框事件固定名称
+- `filter` 为复选框元素对应的 `lay-filter` 属性值
+
+该事件在复选框选中或取消选中时触发。
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/form/examples/checkbox.skin.md b/docs/form/examples/checkbox.skin.md
new file mode 100644
index 000000000..9421226aa
--- /dev/null
+++ b/docs/form/examples/checkbox.skin.md
@@ -0,0 +1,92 @@
+
+
+
+
+
+
+
diff --git a/docs/form/examples/checkboxAndRadio.style.md b/docs/form/examples/checkboxAndRadio.style.md
new file mode 100644
index 000000000..e7a434af5
--- /dev/null
+++ b/docs/form/examples/checkboxAndRadio.style.md
@@ -0,0 +1,192 @@
+
+
+
+
+
+
diff --git a/docs/form/examples/form.demo.md b/docs/form/examples/form.demo.md
new file mode 100644
index 000000000..c6082ad78
--- /dev/null
+++ b/docs/form/examples/form.demo.md
@@ -0,0 +1,259 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
普通文本域
+
+ <textarea placeholder="请输入内容" class="lay-textarea"></textarea>
+
+
+
+
+
+
+
+
diff --git a/docs/form/examples/form.grid.md b/docs/form/examples/form.grid.md
new file mode 100644
index 000000000..4bf2695c3
--- /dev/null
+++ b/docs/form/examples/form.grid.md
@@ -0,0 +1,109 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Search
+ Reset
+
+
+
+
+
diff --git a/docs/form/examples/form.login.md b/docs/form/examples/form.login.md
new file mode 100644
index 000000000..dcf6fd59d
--- /dev/null
+++ b/docs/form/examples/form.login.md
@@ -0,0 +1,80 @@
+
+
+
+
+
+
+
diff --git a/docs/form/examples/form.pane.md b/docs/form/examples/form.pane.md
new file mode 100644
index 000000000..f18035ede
--- /dev/null
+++ b/docs/form/examples/form.pane.md
@@ -0,0 +1,102 @@
+
+
+
+
+
+
+
+
+
+
+
文本域
+
+ <textarea placeholder="请输入内容" class="lay-textarea"></textarea>
+
+
+
+ 确认
+ 重置
+
+
+
+
+
diff --git a/docs/form/examples/form.reg.md b/docs/form/examples/form.reg.md
new file mode 100644
index 000000000..4613c2c16
--- /dev/null
+++ b/docs/form/examples/form.reg.md
@@ -0,0 +1,131 @@
+
+
+
+
+
+
+
diff --git a/docs/form/examples/form.val.md b/docs/form/examples/form.val.md
new file mode 100644
index 000000000..a4689aa54
--- /dev/null
+++ b/docs/form/examples/form.val.md
@@ -0,0 +1,113 @@
+
+
+ 赋值
+ 取值
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
文本域
+
+ <textarea placeholder="请输入" class="lay-textarea" name="desc"></textarea>
+
+
+
+
+
+
+
+
diff --git a/docs/form/examples/form.validate.md b/docs/form/examples/form.validate.md
new file mode 100644
index 000000000..30fbba6cd
--- /dev/null
+++ b/docs/form/examples/form.validate.md
@@ -0,0 +1,57 @@
+
+
+
+
diff --git a/docs/form/examples/form.verify.md b/docs/form/examples/form.verify.md
new file mode 100644
index 000000000..76ce4f0d9
--- /dev/null
+++ b/docs/form/examples/form.verify.md
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+ 提交
+
+
+
+
+
diff --git a/docs/form/examples/input.affix.custom.md b/docs/form/examples/input.affix.custom.md
new file mode 100644
index 000000000..3d2ae2fa9
--- /dev/null
+++ b/docs/form/examples/input.affix.custom.md
@@ -0,0 +1,40 @@
+
+
+
+
diff --git a/docs/form/examples/input.group.md b/docs/form/examples/input.group.md
new file mode 100644
index 000000000..c2eebee05
--- /dev/null
+++ b/docs/form/examples/input.group.md
@@ -0,0 +1,84 @@
+
+
+
diff --git a/docs/form/examples/input.pre.suf.md b/docs/form/examples/input.pre.suf.md
new file mode 100644
index 000000000..0221bbfff
--- /dev/null
+++ b/docs/form/examples/input.pre.suf.md
@@ -0,0 +1,96 @@
+
+
+
diff --git a/docs/form/examples/radio.skin.md b/docs/form/examples/radio.skin.md
new file mode 100644
index 000000000..3a31be7f2
--- /dev/null
+++ b/docs/form/examples/radio.skin.md
@@ -0,0 +1,104 @@
+
+
+
+
+
+
+
diff --git a/docs/form/index.md b/docs/form/index.md
new file mode 100644
index 000000000..ef12d613b
--- /dev/null
+++ b/docs/form/index.md
@@ -0,0 +1,464 @@
+---
+title: 表单组件 form
+toc: true
+---
+
+# 表单组件 🔥
+
+> 表单组件`form`是包含输入框、选择框、复选框、开关、单选框等表单项组件的集合,主要用于对表单域进行各类动态化渲染和相关的交互操作。`form`是 Layui 最常用的组件之一。
+
+示例
+
+综合演示
+
+
+
+{{- d.include("/form/examples/form.demo.md") }}
+
+
+
+方框风格
+
+
+
+{{- d.include("/form/examples/form.pane.md") }}
+
+
+
+登录模板 2.8+
+
+
+
+{{- d.include("/form/examples/form.login.md") }}
+
+
+
+注册模板 2.8+
+
+
+
+{{- d.include("/form/examples/form.reg.md") }}
+
+
+
+更多其他表单模板均可自由布局实现,为了避免影响文档其他重要版面的阅读,我们就不做过多演示了。
+
+
+表单布局
+
+### 🌕 普通布局
+
+在上文的「[综合演示](#examples)」示例中,我们用的是 form 组件自身的普通布局。其要点为:
+
+- 通过 `class="lay-form"` 定义一个表单域,通常设置在``标签上, 或普通`` 标签亦可。
+- 通过 `class="lay-form-item"` 定义一个块级元素的表单项容器
+- 通过 `class="lay-form-label"` 定义标签
+- 通过 `class="lay-input-block"` 定义表单项父容器为块级元素
+- 通过 `class="lay-input-inline"` 或 `class="lay-inline"` 定义表单项父容器为行内块元素
+
+即必须按照规定的层级定义相应的 `class`。
+
+### 🌕 栅格布局
+
+form 还可以借助*栅格*实现更灵活的响应式布局。
+
+
+
+{{- d.include("/form/examples/form.grid.md") }}
+
+
+
+
API
+
+| API | 描述 |
+| --- | --- |
+| var form = layui.form | 获得 `form` 模块。 |
+| [form.render(type, filter)](#render) | 表单域组件渲染,核心方法。[#用法](#render) |
+| [form.verify(obj)](#verify) | 自定义表单验证的规则。[#用法](#verify) |
+| [form.validate(elem)](#validate)
2.7+ | 主动触发执行验证。[#用法](#validate) |
+| [form.val(filter, obj)](#val) | 表单赋值或取值。 [#用法](#val) |
+| [form.submit(filter, callback)](#submit)
2.7+ | 用于主动执行指定表单的提交。[#用法](#submit) |
+| [form.on(\'event(filter)\', callback)](#on) | 事件。[#用法](#on) |
+| [form.set(options)](#set) | 设置 form 组件全局配置项。 |
+| form.config | 获取 form 组件全局配置项。 |
+
+
属性
+
+在表单域中,有时还需要定义一些特定属性来配合组件的使用,它们一般以 `lay-*` 为命名格式,如:
+
+```
+
+
+
+ 提交
+
+
+```
+
+以下为 `form` 组件的特定属性列表:
+
+| 属性 | 值 | 描述 |
+| --- | --- | --- |
+| title | 自定义 | 设置表单元素标题,一般用于 `checkbox,radio` 元素 |
+| lay-filter | 自定义 | 设置表单元素的过滤器,以便用于执行相关方法时的参数匹配 |
+| lay-verify | `required`必填项
`phone`手机号
`email`邮箱
`url`网址
`number`数字
`date`日期
`identity`身份证
`自定义规则值` | 设置表单项的验证规则,支持单条或多条规则(多条用`\|`分隔),如:
`lay-verify="required"`
`lay-verify="required\|email"`
`lay-verify="其他自定义规则值"`
自定义规则的用法:[#详见](#verify)
注:
2.8.3 版本中调整了内置规则,不再强制必填。
如需保留必填,可叠加 `required` 规则,如:
`lay-verify="required\|number"` |
+| lay-vertype | `tips`吸附层
`alert` 对话框
`msg` 默认 | 设置验证异常时的提示层模式 |
+| lay-reqtext | 自定义 | 设置*必填项*(`lay-verify="required"`)的默认提示文本 |
+| lay-affix | [#详见](input.html#affix) | 输入框动态点缀,`
`元素 **私有属性** |
+| lay-skin | [#详见](checkbox.html#default) | 设置 UI 风格。 `
`,`
` 元素 **私有属性** |
+| lay-search |
2.9.15+ `lay-search="{caseSensitive:false, fuzzy: false}"`
`caseSensitive` 是否区分大小写,默认值为 `false`
`fuzzy`是否开启模糊匹配,开启后将会忽略匹配字符出现在字符串中的位置,默认值为 `false`
设置`cs`区分大小写(2.9.15+ 已弃用) | 给 `select` 组件开启搜索功能。`
` 元素 **私有属性** |
+| lay-creatable 2.9.7+ | 无需值 | 是否允许创建新条目,需要配合 `lay-search` 使用。`` 元素 **私有属性** |
+| lay-append-to 2.9.12+ 实验性 | `body` | 是否将 select 面板追加到 body 元素中。`` 元素 **私有属性** |
+| lay-append-position 2.9.12+ 实验性 | `absolute` 绝对定位 (默认) `fixed` 固定定位 | 用于设置 select 面板开启 `lay-append-to` 属性后的定位方式。`` 元素 **私有属性** |
+| lay-submit | 无需值 | 设置元素(一般为`` 标签)触发 `submit` 提交事件 |
+| lay-ignore | 无需值 | 设置表单元素忽略渲染,即让元素保留系统原始 UI 风格。注 2.10.2+ :该属性若设置在 `` 等父元素上,则该父元素下的所有表单均可被忽略渲染。 |
+
+
+
渲染
+
+`form.render(type, filter);`
+
+- 参数 `type` 可选,对应表单组件类型,支持:`input,select,checkbox,radio`;若不填,则指向所有类型。
+- 参数 `filter` 可选,对应 `class="lay-form"` 所在元素的 `lay-filter` 属性值,用于指定需渲染的表单区域。
+
+### **常规渲染**
+
+`form` 组件会在元素加载完毕后,自动对所有表单区域完成一次渲染,因此该方法主要用于对*动态插入*的表单元素的渲染。
+
+```
+
+ 动态插入的表单域
+
+
+
+
+```
+
+### **定向渲染**
2.7+
+
+该方法还允许指定表单元素的 jQuery 对象,从而完成定向渲染。且支持两种方式的指向:
+
+- 若 jQuery 对象指向表单域容器(`class="lay-form"`),则渲染该表单域中的所有表单项;
2.8+
+- 若 jQuery 对象指向的不是表单域容器,则只对该对象进行渲染
+
+定向渲染在页面出现大量表单时,可以极大地减少表单组件渲染时的性能开销,建议灵活运用。
+
+```
+
+
+ A
+
+
+
+
+
+
+```
+
+### **忽略渲染**
+
+若表单域中的部分表单不需要 Layui 来渲染,那么可通过 `lay-ignore` 属性让其保留系统原始 UI 风格。
+
+
+
+
+
+ 正常渲染的 select
+
+
+
+
+ 忽略渲染的 select
+
+ 忽略渲染的 checkbox
+
+
+
+
+
+
验证
+
+Layui 对表单验证做了巧妙的支持,只需在表单元素上设置 `lay-verify=""` 属性值即可指定验证规则,如:
+
+```
+
+
+
+
+ 提交
+
+```
+
+注:上述代码指定的均为内置的验证规则,具体可参考:[#属性介绍](#attr)
+
+
自定义验证规则
+
+`form.verify(obj);`
+
+- 参数 `obj` 是一个对象,用于定义验证规则的集合。
+
+除了内置的验证规则外,form 还允许自定义验证规则,规则以函数命名,返回的参数如下:
+
+```
+// 自定义验证规则
+form.verify({
+ rule: function(value, elem) {
+ console.log(value); // 当前进入验证的表单项的值
+ console.log(elem); // 当前进入验证的表单项的 DOM 元素
+ }
+});
+```
+
+在自定义规则中,可根据规则函数返回的 value 自行判断是否必填,如:
+
+```
+form.verify({
+ // 必填项
+ rule1: function(value, elem) {
+ // 自定义规则
+ if (value.length < 6) {
+ return '不能小于 6 个字符';
+ }
+ },
+ // 非必填项,只有当值填写时才验证自定义规则
+ rule2: function(value, elem) {
+ if (!value) return; // 若值未填写,不进行后续规则验证
+
+ // 自定义规则
+ if (/^[A-Z]/.test(value)) {
+ return '必须用大写字符开头';
+ }
+ },
+ // 自定义提示方式
+ rule3: function(value, elem) {
+ // 自定义规则和自定义提示方式
+ if(value === 'xxx'){
+ alert('用户名不能为敏感词'); // 此处以系统自带的 alert 提示方式为例
+ return true; // 返回 true 即可阻止 form 默认的提示风格
+ }
+ }
+});
+```
+
+以下是一个自定义验证规则的示例:
+
+
+
+{{- d.include("/form/examples/form.verify.md") }}
+
+
+
+更多「自定义验证规则」示例参考:
+
+> -
将 form 提示语显示在表单项旁边,并在提交时批量触发验证
+
+
+
主动触发验证 2.7+
+
+`form.validate(elem);`
+
+- 参数 `elem` 为元素选择器或 jQuery 对象; 若验证通过,该方法将返回 true,否则返回 false
+
+
+
+{{- d.include("/form/examples/form.validate.md") }}
+
+
+
+
+
赋值/取值
+
+`form.val(filter, obj);`
+
+- 参数 `filter` 为表单域容器(`class="lay-form"`)的 `lay-filter` 属性值
+- 参数 `obj` 可选。若参数存在,则对表单域进行赋值;若参数不存在,则为对表单域进行取值。
+
+
+
+{{- d.include("/form/examples/form.val.md") }}
+
+
+
+
+
提交
+
+表单的提交可以通过事件触发或方法触发
+
+### **提交事件**
+
+在表单域中,对指定按钮设置 `lay-submit` 属性,即意味着点击该按钮时,将触发提交事件。如:
+
+
+
+
+
+
+ 提交按钮
+ 普通按钮
+
+
+
+
+
+
+
+### **提交方法**
2.7+
+
+`form.submit(filter, callback);`
+
+- 参数 `filter` 为表单域容器的 `lay-filter` 属性值
+- 参数 `callback` 为执行提交事件后的回调函数
+
+使用该方法可以实现在任意位置对指定表单的主动提交,相比上述的提交事件更加灵活。
+
+
+
+
+ 表单内部
+
+
+
+
+
+
+
+任意位置按钮
+
+
+
+
+
+
+
事件
+
+`form.on('event(filter)', callback);`
+
+- 参数 `event(filter)` 是一个特定结构。`event` 为事件名,支持:`select,checkbox,switch,radio,submit`;`filter` 为元素属性 `lay-filter` 对应的值,若不填,则指向所有同类组件的事件。
+- 参数 `callback` 为事件执行时的回调函数,并返回一个包含各种值的 `object` 类型的参数。
+
+如下以 `select` 事件为例:
+```
+// 指向所有 select 组件的选择事件
+form.on('select', function(data){
+ console.log(data);
+});
+
+// 指向元素为 `
` 的选择事件
+form.on('select(test)', function(data){
+ console.log(data);
+});
+```
+
+
全局设置
+
+`form.set(options);`
+
+- 参数 `options` : 全局属性选项。详见下表:
+
+| 属性名 | 描述 | 类型 | 默认值 |
+| --- | --- | --- | --- |
+| autocomplete | 设置 input 框的 `autocomplete` 属性初始值 | string | - |
+
+该方法用于对 form 组件进行全局设置。
+
+```
+form.set({
+ autocomplete: 'off' // 阻止 input 框默认的自动输入完成功能
+});
+```
+
diff --git a/docs/form/input.md b/docs/form/input.md
new file mode 100644
index 000000000..fb7ea8256
--- /dev/null
+++ b/docs/form/input.md
@@ -0,0 +1,248 @@
+---
+title: 输入框 / 文本域
+toc: true
+---
+
+# 输入框
+
+> 输入框组件是对文本框`
`和多行文本框`
`元素的扩展
+
+
+普通输入框
+
+
+
+
+
+
+ <textarea name="" placeholder="多行文本框" class="lay-textarea"></textarea>
+
+
+
+
+
+输入框点缀 2.8+
+
+输入框点缀是指给普通输入框附加其他元素来进行动静态修饰,其结构包含:*容器、前缀、输入框、后缀*。
+
+```
+
+```
+
+- 容器类:
+ - 前置和后置结构:`class="lay-input-group"`
+ - 前缀和后缀结构:`class="lay-input-wrap"`
+- 前缀类:`class="lay-input-prefix"`
+- 后缀类:`class="lay-input-suffix"`
+- 前缀显示分隔框:`class="lay-input-prefix lay-input-split"`
+- 后缀显示分隔框:`class="lay-input-suffix lay-input-split"`
+
+通过在不同层级中设置规定的 CSS 类来实现点缀布局,再按照不同需求,在前缀和后缀中放置图标等任意内容。
+
+
+前置和后置
+
+前置和后置结构是*输入框的自适应结构*,可以很灵活地控制前后置内容与输入框的宽度比例。
+
+- 结构:
+
+```
+
+```
+
+- 示例:
+
+
+
+{{- d.include("/form/examples/input.group.md") }}
+
+
+
+
+前缀和后缀
+
+输入框前缀和后缀是*输入框的纯修饰结构*,前缀和后缀宽度固定且其元素不可触及,即只能触及输入框本身。
+
+- 结构:
+
+```
+
+```
+
+- 示例:
+
+
+
+{{- d.include("/form/examples/input.pre.suf.md") }}
+
+
+
+注意「前置和后置」与「前缀和后缀」 二者使用时切勿混淆。
+
+
+动态点缀 2.8+
+
+该功能允许对输入框内容进行相关动态操作。通过对输入框元素设置 `lay-affix` 属性来开启动态点缀。
+
+| 点缀 | 属性值 |
+| --- | --- |
+| [数字输入框](#affix-number) 2.8.9+ | `lay-affix="number"` |
+| [密码框显隐](#affix-eye) | `lay-affix="eye"` |
+| [内容清除](#affix-clear) | `lay-affix="clear"` |
+| [自定义动态点缀](#affix-custom) | `lay-affix="customName"` |
+
+
+
+ 数字输入框 2.8.9+
+
+
+一般搭配 ` ` 使用,用于替代原生数字输入框,支持的属性如下:
+注:2.10+ 之前的版本,使用 `type="number"` 类型的输入框。
+
+| 属性 | 描述 |
+| --- | --- |
+| step | 设置数字的加减间隔 |
+| min | 设置数字的最小值 |
+| max | 设置数字的最大值 |
+| lay-precision 2.8.18+ | 设置数字的小数位精度。注2.9.8+ :若值为 `0`,则表示取整。 |
+| lay-step-strictly 2.10+ | 步长严格模式,只能输入步长的倍数 |
+| lay-wheel 2.10+ | 是否启用滚轮或触摸板事件处理 |
+
+### 示例
+
+
+
+
+
+
+
+
+
+
+密码显隐
+
+一般搭配 ` ` 使用,用于控制输入框内容的显示和隐藏。
+
+
+
+
+
+
+
+
+
+内容清除
+
+一般搭配 ` ` 使用,用于清除输入框的内容。
+
+
+
+
+
+
+
+
+
+自定义动态点缀
+
+我们还可以对 `lay-affix` 属性设置任意图标值,从而实现自定义动态点缀功能。 其中 `lay-affix="customName"` 值对应图标类`lay-icon-`后面的名称([#详见图标列表](../icon/#list))。且可通过「[点缀事件](#affix-event)」完成自定义操作。
+
+
+
+{{- d.include("/form/examples/input.affix.custom.md") }}
+
+
+
+输入框的自定义动态点缀功能,让原本单一的输入框有了更多的想象空间。
+
+
+点缀事件
+
+`form.on('input-affix(filter)', callback);`
+
+- `input-affix` 为输入框动态点缀事件固定名称
+- `filter` 为输入框对应的 `lay-filter` 属性值
+
+该事件在点击输入框的点缀图标时触发,通过该事件可以完成一些自定义操作。
+
+```
+form.on('input-affix(filter)', function(data){
+ var elem = data.elem; // 获取输入框 DOM 对象
+ var affix = data.affix; // 获取输入框 lay-affix 属性值
+ console.log(this); // 当前触发点缀事件的图标元素
+});
+```
+
+
+
+
+
diff --git a/docs/form/radio.md b/docs/form/radio.md
new file mode 100644
index 000000000..980052987
--- /dev/null
+++ b/docs/form/radio.md
@@ -0,0 +1,123 @@
+---
+title: 单选框
+toc: true
+---
+
+# 单选框
+
+> 单选框组件是对 ` ` 元素的美化替代。
+
+普通单选框
+
+
+
+
+
+
+
+
+
+
+
+
+
+- 属性 `title` 可设置单选框标题
+- 属性 `checked` 可设置默认选中
+- 属性 `disabled` 可设置禁用状态
+- 属性 `value` 可设置值,否则选中时返回的默认值为 `on`(浏览器默认机制)。同组单选框一般设置相同值。
+- 属性 `lay-skin` 可设置单选框风格,可选值:`none`(无样式)2.9.8+ 默认风格可不填
+
+自定义标题模板
+
+在 `radio` 元素后的相邻元素设置特定属性 `lay-radio`,可以与 `radio` 标题进行绑定。
+
+
+
+
+
+
+
+
+
+自定义任意风格 2.9.8+
+
+通过对 `radio` 元素设置 `lay-skin="none"` 属性禁用默认样式,从而实现任意风格的单选组件。
+**注:** 这意味着你需要掌握一定的 `CSS` 技能,以下示例中的样式均为外部自主实现,并非 Layui 内置。
+
+
+
+{{- d.include("/form/examples/radio.skin.md") }}
+
+
+
+单选框事件
+
+`form.on('radio(filter)', callback);`
+
+- `radio` 为单选框事件固定名称
+- `filter` 为单选框元素对应的 `lay-filter` 属性值
+
+该事件在单选框被点击或选中时触发。
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/form/select.md b/docs/form/select.md
new file mode 100644
index 000000000..0f7c62385
--- /dev/null
+++ b/docs/form/select.md
@@ -0,0 +1,285 @@
+---
+title: 选择框
+toc: true
+---
+
+# 选择框
+
+> 选择框组件是对 `` 元素的美化替代,延续了原有的特性,且加入了搜索等扩展。
+
+
+普通选择框
+
+
+
+
+
+
+
+
+
+- 若第一项 `value` 为空,通常只作为选择框提示性引导;若第一项 `value` 不为空,则作为默认选中项。
+- 通过给选项添加 `selected` 属性优先设置默认选中项。
+- 通过给 `` 或 `` 标签设置 `disabled` 可禁用整个选择框或某个选项。
+
+在 `` 标签上同样支持设置表单的其他公共属性([#详见](./#attr))。
+
+分组选择框
+
+通过 `` 标签给选择框分组
+
+
+
+
+
+ 请选择
+
+ 选项 A-1
+ 选项 A-2
+ 选项 A-3
+
+
+ 选项 B-1
+ 选项 B-2
+
+
+
+
+
+
+
+
+
+搜索选择框
+
+在 `` 元素上设置 `lay-search` 可开启选择框的搜索功能,如:`lay-search="{caseSensitive:false, fuzzy: false}"`,支持的可选项如下:
+
+- `caseSensitive`:是否区分大小写,默认值 `false`
+- `fuzzy`:是否开启模糊匹配,设置 `true` 开启后将忽略匹配字符出现在字符串中的位置。默认值 `false`
+
+在 `` 元素上设置 `lay-creatable=""` 可允许创建新的 option,需开启 `lay-search` 后生效。
+
+
+
+
+
+
+
+
+
+独立选择框 2.9.12+
+
+在 `` 元素中设置 `lay-append-to="body"` 属性,可将 select 面板插入到 `` 根节点下,以便让选择框从 form 结构中剥离,成为更灵活的独立选择框。借助该特性,可完美解决 select 在 table, layer 等组件中使用的若干问题。
+
+### 1. 在 table 中使用 select
+
+参考 table 示例: [实现多样化编辑](/docs/2/table/#demo-editmodes)
+
+### 2. 在 layer 中使用 select
+
+
+
+弹出 layer+select
+
+
+
+
+
+
+
+选择框事件
+
+`form.on('select(filter)', callback);`
+
+- `select` 为选择框事件固定名称
+- `filter` 为选择框元素对应的 `lay-filter` 属性值
+
+该事件在选择框选项选中后触发。
+
+
+
+
+
+ 请选择
+ 选项 A
+ 选项 B
+ 选项 C
+
+
+
+
+
+
+
+
diff --git a/docs/i18n/detail/demo.md b/docs/i18n/detail/demo.md
new file mode 100644
index 000000000..20fcb498b
--- /dev/null
+++ b/docs/i18n/detail/demo.md
@@ -0,0 +1,785 @@
+
+
+
+
+ i18n 演示 - Layui
+
+
+
+
+
{{!
+
+ {{ const i18n = layui.i18n; }}
+
+
+
+ README
+
+
{{= i18n.$t('custom.readme.description') }}
+
+ locale : {{= i18n.config.locale }}
+ Date : {{= new Date().toLocaleDateString(i18n.config.locale) }}
+ Hello : {{= i18n.$t('custom.readme.hello') }}
+
+
+
+
+ code
+
+
+
+ colorpicker
+
+
+
+ dropdown
+
+
+ Dropdown
+
+
+
+
+
+ flow
+
+
+
+ form
+
+
+
+ laydate
+
+
+
+ layer
+
+ Alert
+ Prompt
+ Photos
+
+
+
+ laypage
+
+
+
+ table
+
+
+
+ transfer
+
+
+
+ tree
+
+
+
+ upload
+
+
+ Upload
+
+
+
+
+ utils
+
+
+ timeAgo:
+
+
+
+ toDateString:
+
+
+
+ !}}
+
+
+
+
+
+
+
+
diff --git a/docs/i18n/detail/options.md b/docs/i18n/detail/options.md
new file mode 100644
index 000000000..aa5fb5be5
--- /dev/null
+++ b/docs/i18n/detail/options.md
@@ -0,0 +1,185 @@
+
+
+// 简体中文语言包(内置)
+var zhCN = {
+ code: {
+ copy: '复制代码',
+ copied: '已复制',
+ copyError: '复制失败',
+ maximize: '最大化显示',
+ restore: '还原显示',
+ preview: '在新窗口预览'
+ },
+ colorpicker: {
+ clear: '清除',
+ confirm: '确定'
+ },
+ dropdown: {
+ noData: '暂无数据'
+ },
+ flow: {
+ loadMore: '加载更多',
+ noMore: '没有更多了'
+ },
+ form: {
+ select: {
+ noData: '暂无数据',
+ noMatch: '无匹配数据',
+ placeholder: '请选择'
+ },
+ validateMessages: {
+ required: '必填项不能为空',
+ phone: '手机号格式不正确',
+ email: '邮箱格式不正确',
+ url: '链接格式不正确',
+ number: '只能填写数字',
+ date: '日期格式不正确',
+ identity: '身份证号格式不正确'
+ },
+ verifyErrorPromptTitle: '提示'
+ },
+ laydate: {
+ months: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
+ weeks: ['日', '一', '二', '三', '四', '五', '六'],
+ time: ['时', '分', '秒'],
+ literal: {
+ year: '年'
+ },
+ selectDate: '选择日期',
+ selectTime: '选择时间',
+ startTime: '开始时间',
+ endTime: '结束时间',
+ tools: {
+ confirm: '确定',
+ clear: '清空',
+ now: '现在',
+ reset: '重置'
+ },
+ rangeOrderPrompt: '结束时间不能早于开始时间\n请重新选择',
+ invalidDatePrompt: '不在有效日期或时间范围内\n',
+ formatErrorPrompt: '日期格式不合法\n必须遵循:\n{format}\n',
+ autoResetPrompt: '已自动重置',
+ preview: '当前选中的结果'
+ },
+ layer: {
+ confirm: '确定',
+ cancel: '取消',
+ defaultTitle: '信息',
+ prompt: {
+ InputLengthPrompt: '最多输入 {length} 个字符'
+ },
+ photos: {
+ noData: '没有图片',
+ tools:{
+ rotate: '旋转',
+ scaleX: '水平变换',
+ zoomIn: '放大',
+ zoomOut: '缩小',
+ reset: '还原',
+ close: '关闭'
+ },
+ viewPicture: '查看原图',
+ urlError: {
+ prompt: '当前图片地址异常,\n是否继续查看下一张?',
+ confirm: '下一张',
+ cancel: '不看了'
+ }
+ }
+ },
+ laypage: {
+ prev: '上一页',
+ next: '下一页',
+ first: '首页',
+ last: '尾页',
+ total: '共 {total} 条',
+ pagesize: '条/页',
+ goto: '到第',
+ page: '页',
+ confirm: '确定'
+ },
+ table: {
+ sort: {
+ asc: '升序',
+ desc: '降序'
+ },
+ noData: '暂无数据',
+ tools:{
+ filter: {
+ title: '筛选列'
+ },
+ export: {
+ title: '导出',
+ noDataPrompt: '当前表格无数据',
+ csvText : '导出 CSV 文件'
+ },
+ print: {
+ title: '打印',
+ noDataPrompt: '当前表格无数据'
+ }
+ },
+ dataFormatError: '返回的数据不符合规范,正确的成功状态码应为:"{statusName}": {statusCode}',
+ xhrError: '请求异常,错误提示:{msg}'
+ },
+ transfer: {
+ noData: '暂无数据',
+ noMatch: '无匹配数据',
+ title: ['列表一', '列表二'],
+ searchPlaceholder: '关键词搜索'
+ },
+ tree: {
+ defaultNodeName: '未命名',
+ noData: '暂无数据',
+ deleteNodePrompt: '确认删除"{name}"节点吗?'
+ },
+ upload: {
+ fileType: {
+ file: '文件',
+ image: '图片',
+ video: '视频',
+ audio: '音频'
+ },
+ validateMessages: {
+ fileExtensionError: '选择的{fileType}中包含不支持的格式',
+ filesOverLengthLimit: '同时最多只能上传: {length} 个文件',
+ currentFilesLength: '当前已经选择了: {length} 个文件',
+ fileOverSizeLimit: '文件大小不能超过 {size}'
+ },
+ chooseText: '{length} 个文件'
+ },
+ util: {
+ timeAgo: {
+ days: '{days} 天前',
+ hours: '{hours} 小时前',
+ minutes: '{minutes} 分钟前',
+ future: '未来',
+ justNow: '刚刚'
+ },
+ toDateString: {
+ // https://www.unicode.org/cldr/charts/47/supplemental/day_periods.html
+ meridiem: function(hours, minutes){
+ var hm = hours * 100 + minutes;
+ if (hm < 500) {
+ return '凌晨';
+ } else if (hm < 800) {
+ return '早上';
+ } else if (hm < 1200) {
+ return '上午';
+ } else if (hm < 1300) {
+ return '中午';
+ } else if (hm < 1900) {
+ return '下午';
+ }
+ return '晚上';
+ }
+ }
+ }
+};
+i18n.set({
+ locale: 'zh-CN', // 设置语言环境
+ messages: { // 语言包
+ 'zh-CN': zhCN
+ }
+});
+
+
+
diff --git a/docs/i18n/index.md b/docs/i18n/index.md
new file mode 100644
index 000000000..f0ff31f6e
--- /dev/null
+++ b/docs/i18n/index.md
@@ -0,0 +1,111 @@
+---
+title: 国际化 i18n
+toc: true
+---
+
+# 国际化 2.12+
+
+> `i18n` 是 2.12 版本新增的国际化模块,用于为 Layui 各组件实现多语言支持。
+
+完整演示
+
+为了避免语言包配置冗长而影响示例源代码的查看,此处只演示「简体中文 / English / 繁體中文」语言环境,你可以点击该示例头部的「切换语言」选择框查看 Layui 组件在不同语言环境中的显示效果。
+
+
+
+
+
+{{- d.include("/i18n/detail/demo.md") }}
+
+
+
+API
+
+| API | 描述 |
+| --- | --- |
+| var i18n = layui.i18n | 获得 `i18n` 模块。|
+| [i18n.set(options)](#set) | 设置语言环境及语言包。|
+
+配置方式
+
+i18n 支持两种配置方式,你可以根据实际应用场景选择任一方式。
+
+#### 1. 通过 `i18n.set()` 方法配置
+
+`i18n.set(options)`
+
+- 参数 `options` : 基础属性选项。[#详见语言包选项](#options)
+
+```js
+layui.use(function() {
+ var i18n = layui.i18n;
+
+ // 设置语言
+ i18n.set({
+ locale: 'zh-CN', // 当前语言环境。zh-CN 为内置简体中文语言包
+ messages: { // 扩展其他语言包
+ 'en': {},
+ 'zh-HK': {},
+ }
+ });
+});
+```
+
+🔔 请注意:如果你的页面有用到 Layui 组件的自动渲染(如 table 模板配置渲染方式),因为执行顺序的问题,组件在自动渲染时可能无法读取到 `i18n.set()` 的配置信息,此时建议采用下述 `LAYUI_GLOBAL.i18n` 全局配置。
+
+#### 2. 通过 `LAYUI_GLOBAL.i18n` 全局配置(推荐)
+
+由于 i18n 配置与组件渲染存在执行顺序问题,为了确保 i18n 配置始终在组件渲染之前生效,更推荐采用该全局配置方式。
+
+```html
+
+
+```
+
+语言包选项
+
+i18n 默认采用简体中文(`zh-CN`)语言环境,以下为各组件消息文本对应的选项:
+
+
+{{- d.include("/i18n/detail/options.md") }}
+
+
+
+基于上述选项,还可以扩展更多语言包,如:
+
+```js
+i18n.set({
+ locale: 'en', // 当前语言环境
+ messages: { // 扩展更多语言包
+ 'en': { // 通用英语
+ code: {
+ copy: 'Copy Code',
+ copied: 'Copied',
+ // ……
+ },
+ // ……
+ },
+ 'fr': {}, // 通用法语
+ 'zh-HK': {}, // 繁体中文
+ // …… // 更多语言
+ }
+});
+```
+
+对消息文本进行翻译时,为了节省时间,你可以使用 AI 直接生成不同语言的消息文本,或者使用第三方提供的 Layui 多语言 AI 翻译工具(如:https://gitee.com/mail_osc/translate/tree/master/extend/lay-i18n-object-translate By @xnx3 )。
+
+## 💖 心语
+
+i18n 模块是在众多开发者的广泛需求背景下完成开发,它通过简练的设计,为 Layui 组件实现了多语言的无缝接入,并且兼容了一些原本自带简单多语言或消息配置的组件,从而使 Layui 2 系列版本全面支持国际化。
+
diff --git a/docs/icon/index.md b/docs/icon/index.md
new file mode 100644
index 000000000..ae8b69de7
--- /dev/null
+++ b/docs/icon/index.md
@@ -0,0 +1,1252 @@
+---
+title: 图标
+toc: true
+---
+
+# 图标
+
+> Layui 图标采用字体形式,取材于阿里巴巴矢量图标库 `iconfont`,因此可以把一个 `icon` 看作是一个普通的文本,直接通过 `css` 即可设定其样式。图标支持 `font-class` 或 `unicode` 两种格式。
+
+示例
+
+
+
+
+
+ 你可以去定义它的颜色或者大小,如:
+
+
+
+
+
+通过对一个内联元素(如 ``标签)添加基础类 `class="lay-icon"` 来定义一个图标,然后对元素加上图标对应的 `font-class`,即可显示出你想要的图标,如上所示。
+
+
+图标列表(192 个)
+
+
+
+
+
机器人
+

+
lay-icon-bot
+
+
+
+
叶子节点
+

+
lay-icon-leaf
+
+
+
+
文件夹
+

+
lay-icon-folder
+
+
+
+
文件夹打开
+

+
lay-icon-folder-open
+
+
+
+
Gitee
+

+
lay-icon-gitee
+
+
+
+
Github
+

+
lay-icon-github
+
+
+
+
+
太阳/明亮
+

+
lay-icon-light
+
+
+
+
月亮
+

+
lay-icon-moon
+
+
+
+
错误
+

+
lay-icon-error
+
+
+
+
成功
+

+
lay-icon-success
+
+
+
+
问号
+

+
lay-icon-question
+
+
+
+
锁定
+

+
lay-icon-lock
+
+
+
+
+
显示
+

+
lay-icon-eye
+
+
+
+
隐藏
+

+
lay-icon-eye-invisible
+
+
+
+
清空/删除
+

+
lay-icon-clear
+
+
+
+
退格
+

+
lay-icon-backspace
+
+
+
+
禁用
+

+
lay-icon-disabled
+
+
+
+
感叹号/提示
+

+
lay-icon-tips-fill
+
+
+
+
+
测试/K线图
+

+
lay-icon-test
+
+
+
+
音乐/音符
+

+
lay-icon-music
+
+
+
+
Chrome
+

+
lay-icon-chrome
+
+
+
+
Firefox
+

+
lay-icon-firefox
+
+
+
+
Edge
+

+
lay-icon-edge
+
+
+
+
IE
+

+
lay-icon-ie
+
+
+
+
实心
+

+
lay-icon-heart-fill
+
+
+
+
空心
+

+
lay-icon-heart
+
+
+
+
时间/历史
+

+
lay-icon-time
+
+
+
+
@艾特
+

+
lay-icon-at
+
+
+
+
邮箱
+

+
lay-icon-email
+
+
+
+
RSS
+

+
lay-icon-rss
+
+
+
+
声音
+

+
lay-icon-sound
+
+
+
+
静音
+

+
lay-icon-mute
+
+
+
+
录音/麦克风
+

+
lay-icon-mike
+
+
+
+
密钥/钥匙
+

+
lay-icon-key
+
+
+
+
礼物/活动
+

+
lay-icon-gift
+
+
+
+
蓝牙
+

+
lay-icon-bluetooth
+
+
+
+
WiFi
+

+
lay-icon-wifi
+
+
+
+
退出/注销
+

+
lay-icon-logout
+
+
+
+
Android 安卓
+

+
lay-icon-android
+
+
+
+
Apple IOS 苹果
+

+
lay-icon-ios
+
+
+
+
Windows
+

+
lay-icon-windows
+
+
+
+
穿梭框
+

+
lay-icon-transfer
+
+
+
+
客服
+

+
lay-icon-service
+
+
+
+
减
+

+
lay-icon-subtraction
+
+
+
+
加
+

+
lay-icon-addition
+
+
+
+
滑块
+

+
lay-icon-slider
+
+
+
+
打印
+

+
lay-icon-print
+
+
+
+
导出
+

+
lay-icon-export
+
+
+
+
列
+

+
lay-icon-cols
+
+
+
+
退出全屏
+

+
lay-icon-screen-restore
+
+
+
+
全屏
+

+
lay-icon-screen-full
+
+
+
+
+
半星
+

+
lay-icon-rate-half
+
+
+
+
星星-空心
+

+
lay-icon-rate
+
+
+
+
星星-实心
+

+
lay-icon-rate-solid
+
+
+
+
手机
+

+
lay-icon-cellphone
+
+
+
+
验证码
+

+
lay-icon-vercode
+
+
+
+
微信
+

+
lay-icon-login-wechat
+
+
+
+
QQ
+

+
lay-icon-login-qq
+
+
+
+
+
微博
+

+
lay-icon-login-weibo
+
+
+
+
密码
+

+
lay-icon-password
+
+
+
+
用户名
+

+
lay-icon-username
+
+
+
+
刷新-粗
+

+
lay-icon-refresh-3
+
+
+
+
授权
+

+
lay-icon-auz
+
+
+
+
左向右伸缩菜单
+

+
lay-icon-spread-left
+
+
+
+
右向左伸缩菜单
+

+
lay-icon-shrink-right
+
+
+
+
+
雪花
+

+
lay-icon-snowflake
+
+
+
+
提示说明
+

+
lay-icon-tips
+
+
+
+
便签
+

+
lay-icon-note
+
+
+
+
主页
+

+
lay-icon-home
+
+
+
+
高级
+

+
lay-icon-senior
+
+
+
+
刷新
+

+
lay-icon-refresh
+
+
+
+
刷新
+

+
lay-icon-refresh-1
+
+
+
+
+
旗帜
+

+
lay-icon-flag
+
+
+
+
主题
+

+
lay-icon-theme
+
+
+
+
消息-通知
+

+
lay-icon-notice
+
+
+
+
网站
+

+
lay-icon-website
+
+
+
+
控制台
+

+
lay-icon-console
+
+
+
+
表情-惊讶
+

+
lay-icon-face-surprised
+
+
+
+
设置-空心
+

+
lay-icon-set
+
+
+
+
+
模板
+

+
lay-icon-template-1
+
+
+
+
应用
+

+
lay-icon-app
+
+
+
+
模板
+

+
lay-icon-template
+
+
+
+
赞
+

+
lay-icon-praise
+
+
+
+
踩
+

+
lay-icon-tread
+
+
+
+
男
+

+
lay-icon-male
+
+
+
+
+
女
+

+
lay-icon-female
+
+
+
+
相机-空心
+

+
lay-icon-camera
+
+
+
+
相机-实心
+

+
lay-icon-camera-fill
+
+
+
+
菜单-水平
+

+
lay-icon-more
+
+
+
+
菜单-垂直
+

+
lay-icon-more-vertical
+
+
+
+
金额-人民币
+

+
lay-icon-rmb
+
+
+
+
金额-美元
+

+
lay-icon-dollar
+
+
+
+
钻石-等级
+

+
lay-icon-diamond
+
+
+
+
+
火
+

+
lay-icon-fire
+
+
+
+
返回
+

+
lay-icon-return
+
+
+
+
位置-地图
+

+
lay-icon-location
+
+
+
+
办公-阅读
+

+
lay-icon-read
+
+
+
+
调查
+

+
lay-icon-survey
+
+
+
+
表情-微笑
+

+
lay-icon-face-smile
+
+
+
+
表情-哭泣
+

+
lay-icon-face-cry
+
+
+
+
+
购物车
+

+
lay-icon-cart-simple
+
+
+
+
购物车
+

+
lay-icon-cart
+
+
+
+
下一页
+

+
lay-icon-next
+
+
+
+
上一页
+

+
lay-icon-prev
+
+
+
+
上传-空心-拖拽
+

+
lay-icon-upload-drag
+
+
+
+
上传-实心
+

+
lay-icon-upload
+
+
+
+
下载-圆圈
+

+
lay-icon-download-circle
+
+
+
+
+
组件
+

+
lay-icon-component
+
+
+
+
文件-粗
+

+
lay-icon-file-b
+
+
+
+
用户
+

+
lay-icon-user
+
+
+
+
发现-实心
+

+
lay-icon-find-fill
+
+
+
+
loading
+

+
lay-icon-loading
+
+
+
+
loading
+

+
lay-icon-loading-1
+
+
+
+
添加
+

+
lay-icon-add-1
+
+
+
+
+
播放
+

+
lay-icon-play
+
+
+
+
暂停
+

+
lay-icon-pause
+
+
+
+
音频-耳机
+

+
lay-icon-headset
+
+
+
+
视频
+

+
lay-icon-video
+
+
+
+
语音-声音
+

+
lay-icon-voice
+
+
+
+
消息-通知-喇叭
+

+
lay-icon-speaker
+
+
+
+
删除线
+

+
lay-icon-fonts-del
+
+
+
+
+
代码
+

+
lay-icon-fonts-code
+
+
+
+
HTML
+

+
lay-icon-fonts-html
+
+
+
+
字体加粗
+

+
lay-icon-fonts-strong
+
+
+
+
删除链接
+

+
lay-icon-unlink
+
+
+
+
图片
+

+
lay-icon-picture
+
+
+
+
链接
+

+
lay-icon-link
+
+
+
+
表情-笑-粗
+

+
lay-icon-face-smile-b
+
+
+
+
+
左对齐
+

+
lay-icon-align-left
+
+
+
+
右对齐
+

+
lay-icon-align-right
+
+
+
+
居中对齐
+

+
lay-icon-align-center
+
+
+
+
字体-下划线
+

+
lay-icon-fonts-u
+
+
+
+
字体-斜体
+

+
lay-icon-fonts-i
+
+
+
+
Tabs 选项卡
+

+
lay-icon-tabs
+
+
+
+
单选框-选中
+

+
lay-icon-radio
+
+
+
+
+
单选框-候选
+

+
lay-icon-circle
+
+
+
+
编辑
+

+
lay-icon-edit
+
+
+
+
分享
+

+
lay-icon-share
+
+
+
+
删除
+

+
lay-icon-delete
+
+
+
+
表单
+

+
lay-icon-form
+
+
+
+
手机-细体
+

+
lay-icon-cellphone-fine
+
+
+
+
聊天 对话 沟通
+

+
lay-icon-dialogue
+
+
+
+
+
文字格式化
+

+
lay-icon-fonts-clear
+
+
+
+
窗口
+

+
lay-icon-layer
+
+
+
+
日期
+

+
lay-icon-date
+
+
+
+
水 下雨
+

+
lay-icon-water
+
+
+
+
代码-圆圈
+

+
lay-icon-code-circle
+
+
+
+
轮播组图
+

+
lay-icon-carousel
+
+
+
+
翻页
+

+
lay-icon-prev-circle
+
+
+
+
+
布局
+

+
lay-icon-layouts
+
+
+
+
工具
+

+
lay-icon-util
+
+
+
+
选择模板
+

+
lay-icon-templeate-1
+
+
+
+
上传-圆圈
+

+
lay-icon-upload-circle
+
+
+
+
树
+

+
lay-icon-tree
+
+
+
+
表格
+

+
lay-icon-table
+
+
+
+
图表
+

+
lay-icon-chart
+
+
+
+
+
图标 报表 屏幕
+

+
lay-icon-chart-screen
+
+
+
+
引擎
+

+
lay-icon-engine
+
+
+
+
下三角
+

+
lay-icon-triangle-d
+
+
+
+
右三角
+

+
lay-icon-triangle-r
+
+
+
+
文件
+

+
lay-icon-file
+
+
+
+
设置-小型
+

+
lay-icon-set-sm
+
+
+
+
减少-圆圈
+

+
lay-icon-reduce-circle
+
+
+
+
添加-圆圈
+

+
lay-icon-add-circle
+
+
+
+
+
+
404
+

+
lay-icon-404
+
+
+
+
关于
+

+
lay-icon-about
+
+
+
+
箭头 向上
+

+
lay-icon-up
+
+
+
+
箭头 向下
+

+
lay-icon-down
+
+
+
+
箭头 向左
+

+
lay-icon-left
+
+
+
+
箭头 向右
+

+
lay-icon-right
+
+
+
+
圆点
+

+
lay-icon-circle-dot
+
+
+
+
+
搜索
+

+
lay-icon-search
+
+
+
+
设置-实心
+

+
lay-icon-set-fill
+
+
+
+
群组
+

+
lay-icon-group
+
+
+
+
好友
+

+
lay-icon-friends
+
+
+
+
回复 评论 实心
+

+
lay-icon-reply-fill
+
+
+
+
菜单 隐身 实心
+

+
lay-icon-menu-fill
+
+
+
+
记录
+

+
lay-icon-log
+
+
+
+
+
图片-细体
+

+
lay-icon-picture-fine
+
+
+
+
表情-笑-细体
+

+
lay-icon-face-smile-fine
+
+
+
+
列表
+

+
lay-icon-list
+
+
+
+
发布 纸飞机
+

+
lay-icon-release
+
+
+
+
对 OK
+

+
lay-icon-ok
+
+
+
+
帮助
+

+
lay-icon-help
+
+
+
+
客服
+

+
lay-icon-chat
+
+
+
+
+
top 置顶
+

+
lay-icon-top
+
+
+
+
收藏-空心
+

+
lay-icon-star
+
+
+
+
收藏-实心
+

+
lay-icon-star-fill
+
+
+
+
关闭-实心
+
ဇ
+
lay-icon-close-fill
+
+
+
+
关闭-空心
+
ဆ
+
lay-icon-close
+
+
+
+
正确
+
စ
+
lay-icon-ok-circle
+
+
+
+
添加-圆圈-细体
+

+
lay-icon-add-circle-fine
+
+
+
+
+跨域处理
+
+由于浏览器存在同源策略,若 Layui 文件地址与你当前的页面地址*不在同一个域下*,即会出现图标跨域问题。因此,要么将 Layui 文件与网站放在同一服务器,要么对 Layui 文件所在的静态资源服务器的 `Response Headers` 添加:`Access-Control-Allow-Origin: *` 或对跨资源共享指定域名,即可解决图标跨域问题。
+
+
+
+
+
+
+
+
+
diff --git a/docs/index.md b/docs/index.md
new file mode 100644
index 000000000..4372fdc0b
--- /dev/null
+++ b/docs/index.md
@@ -0,0 +1,122 @@
+---
+title: 开始使用
+toc: true
+---
+
+开始使用
+
+> Layui 是一套免费的开源 Web UI 组件库,采用自身轻量级模块化规范,遵循原生态的 HTML/CSS/JavaScript 开发模式,极易上手,拿来即用。其风格简约轻盈,而内在雅致丰盈,甚至包括文档在内的每一处细节都经过精心雕琢,非常适合网页界面的快速构建。Layui 区别于一众主流的前端框架,却并非逆道而行,而是信奉返璞归真之道。确切地说,它更多是面向于追求简单的务实主义者,即无需涉足各类构建工具,只需面向浏览器本身,便可将页面所需呈现的元素与交互信手拈来。
+
+
+ Layui
+
+
+
+
+
+ 谐音:类 UI
+ 用途:用于更简单快速地构建网页界面
+
+
+ 环境:详见不同版本的浏览器兼容说明 N
+ 特性:原生态开发 / 轻量级模块化 / 外简内丰 / 开箱即用
+
+
+
+
+下载引用
+
+您可以通过以下任意一种方式获得 Layui :
+
+### 🌕 官网下载
+
+您可以在 [官网首页](/) 或 [更新日志](./versions.html) 页面下载到 Layui,它经过了自动化构建,更适合用于生产环境。目录结构如下:
+
+```
+layui/
+ ├─css
+ │ └─layui.css # 核心样式库
+ └─layui.js # 核心模块库
+```
+
+### 🌕 Git 下载
+
+> 您也可以通过 [GitHub](https://github.com/layui/layui/releases) 或 [Gitee](https://gitee.com/layui/layui/releases) 的 releases 列表下载,或直接下载整个仓库。
+
+
+
+
+
+
+
+### 🌕 npm 下载
+
+```
+npm i layui
+```
+
+### 🌕 第三方 CDN 方式引入:
+
+> 以下均为知名第三方免费开放的公共资源 CDN,每期版本通过 NPM / GitHub 自动同步。
+
+
+
+
+```
+
+
+```
+```
+
+
+```
+
+快速上手
+
+现在,让我们以一个最简单的示例开始入门:
+
+
+
+
+
+
+
+
+ Quick Start - Layui
+
+
+
+
+
+
+
+
+
+
+
+点击上方 `Preview` 标签可进行效果预览。
+
+其他帮助
+
+- 在线测试
+- 深色主题 (社区贡献)
+
+
+## 初识寄语
+
+> 愿 Layui 从此成为您得心应手的 Web 界面解决方案,化作您方寸屏幕前的亿万字节!
+
diff --git a/docs/laydate/detail/demo.md b/docs/laydate/detail/demo.md
new file mode 100644
index 000000000..2ccca60f8
--- /dev/null
+++ b/docs/laydate/detail/demo.md
@@ -0,0 +1,105 @@
+常规用法
+
+
+
+{{- d.include("/laydate/examples/normal.md") }}
+
+
+
+多类型选择器
+
+默认为日期选择器,即上文「常规用法」示例中的效果。以下主要呈现其他类型选择器:
+
+
+
+{{- d.include("/laydate/examples/type.md") }}
+
+
+
+范围选择
+
+
+
+{{- d.include("/laydate/examples/range.md") }}
+
+
+
+配置快捷选项 2.8+
+
+
+
+{{- d.include("/laydate/examples/shortcut.md") }}
+
+
+
+
+
+
+
+
+{{- d.include("/laydate/examples/format.md") }}
+
+
+
+
+节日及标注
+
+
+
+{{- d.include("/laydate/examples/mark.md") }}
+
+
+
+
+限制可选日期
+
+
+
+{{- d.include("/laydate/examples/limit.md") }}
+
+
+
+
+批量绑定元素
+
+
+
+{{- d.include("/laydate/examples/elem.md") }}
+
+
+
+
+更多功能示例
+
+
+
+{{- d.include("/laydate/examples/more.md") }}
+
+
+
+自定义主题
+
+
+
+{{- d.include("/laydate/examples/theme.md") }}
+
+
+
+静态显示
+
+
+
+{{- d.include("/laydate/examples/static.md") }}
+
+
+
+扩展农历 🔥
+
+
+
+{{- d.include("/laydate/examples/cell.md") }}
+
+
+
diff --git a/docs/laydate/detail/options.md b/docs/laydate/detail/options.md
new file mode 100644
index 000000000..69e6616e7
--- /dev/null
+++ b/docs/laydate/detail/options.md
@@ -0,0 +1,860 @@
+
+
+
+
+
+
+
+
+
+ 属性名
+ 描述
+ 类型
+ 默认值
+
+
+
+
+elem
+
+
+绑定元素选择器或 DOM 对象
+
+
+string/DOM
+-
+
+
+
+
+[type](#options.type)
+
+
+
+
+
+ 组件面板选择类型。支持以下可选值:
+
+
+- `year` 年选择器,只提供年列表选择
+- `month` 年月选择器,只提供年、月选择
+- `date` 日期选择器(默认),可选择:年、月、日选择
+- `time` 时间选择器,只提供时、分、秒选择
+- `datetime` 日期时间选择器,可选择:年月日、时分秒
+
+效果详见: [#示例](#demo-type)
+
+
+string
+
+
+`date`
+
+
+
+
+ id
+
+
+设定实例唯一索引,以便用于其他方法对例进行相关操作。若该属性未设置,则默认从 `elem` 属性绑定的元素中的 `id` 属性值中获取。
+
+
+string
+-
+
+
+
+
+[range](#options.range)
+
+
+
+
+
+
+开启左右面板的范围选择,将会根据 `type` 类型呈现对应的范围选择面板。该属性值支持以下类型:
+
+
+
+- 若为 `boolean` 类型,即表示是否开启范围选择,若设为 `true`,则开始日期与结束日期默认采用 `-` 连接符
+- 若为 `string` 类型,则表示开启范围选择,且自定义开始日期与结束日期的连接符。如: `range: '~'`
+- 若为 `array` 类型,即表示开启范围选,且开始日期和结束日期分别赋值在两个目标选择器中,如:
+
+```
+range: ['#start', '#end']
+```
+
+详细用法可参考: [#示例](#demo-range)
+
+
+
+boolean string array
+
+
+`false`
+
+
+
+
+rangeLinked 2.8+
+
+
+是否开启日期范围选择时的区间联动标注模式,该模式必须开启 `range` 属性才能生效。日期范围默认采用的是*左右面板独立选择模式*,设置该属性后,将采用*左右面板联动选择模式*。
+ 效果详见: [#示例](#demo-range)
+
+
+boolean
+
+
+`false`
+
+
+
+
+fullPanel 2.8+
+
+
+是否开启全面板,即日期和时间显示在同一面板。 当 `type: 'datetime'` 且未设置 `range` 属性时生效。
+ 效果详见: [#示例](#demo-type)
+
+
+boolean
+
+
+`false`
+
+
+
+
+
+
+[format](#options.format)
+
+
+
+
+
+
+自定义日期和时间值的返回格式,默认值: `yyyy-MM-dd`。 其格式符规则如下:
+
+
+
+
+| 格式符 | 描述 |
+| --- | --- |
+| yyyy | 年份,输出四个字符。若不足四位,则前置补零 |
+| y | 年份,允许一位 |
+| MM | 月份,输出两个字符。若不足两位,则前置补零 |
+| M | 月份,允许一位 |
+| dd | 日期,输出两个字符。若不足两位,则前置补零 |
+| d | 日期,允许一位 |
+| HH | 小时,输出两个字符。若不足两位,则前面补零 |
+| H | 小时,允许一位 |
+| mm | 分钟,输出两个字符。若不足两位,则前面补零 |
+| m | 分钟,允许一位 |
+| ss | 秒数,输出两个字符。若不足两位,则前面补零 |
+| s | 秒数,允许一位 |
+
+通过上述格式符组成日期时间字符串,如下所示:
+
+```
+// 返回值示例: 2008-08-08 20:08:08
+format: 'yyyy-MM-dd HH:mm:ss'
+
+// 返回值示例: 北京时间 6 点 30 分
+format: '北京时间 H 点 m 分'
+```
+
+相关用法可参考: [#示例](#demo-format)
+
+
+
+
+formatToDisplay 2.9.9+
+
+
+仅用于格式化日期显示的格式,不影响日期值
+
+```
+formatToDisplay: function (value) {
+ // value - 日期字符串
+ var date = new Date(value);
+ var displayValue = [
+ value,
+ date.toLocaleDateString(Intl.LocalesArgument, { weekday: 'long' })
+ ].join(' ');
+ return displayValue;
+};
+
+```
+
+
+function
+-
+
+
+
+
+[value](#options.value)
+
+
+
+
+
+初始值。值支持以下类型:
+
+
+- 若为 `string` 类型,则必须和 `format` 属性格式对应
+
+```
+value: '2018-08-18'
+```
+
+- 若为 `date` 对象类型,则可直接赋值 `new Date()`
+
+```
+value: new Date(1534766888000) // 参数即为:2018-08-20 20:08:08 的毫秒数
+```
+
+- 当开启 `range` 时,初始设置日期范围值
+
+```
+ // 开始日期 - 结束日期
+value: '1900-01-01 - 2100-01-01'
+```
+
+
+string date
+
+
+`new Date()`
+
+
+
+
+isInitValue
+
+
+是否将初始值填充在目标元素中,一般配合 `value` 属性使用
+
+
+boolean
+
+
+`true`
+
+
+
+
+
+
+[shortcuts](#options.shortcuts) 2.8+
+
+
+
+
+
+用于开启面板左侧的快捷选择栏。其值配置规则如下:
+
+
+```
+shortcuts: [
+ {
+ text: "快捷选项文本",
+ value: '快捷选项值'
+ },
+ // 更多选项 …
+]
+```
+
+其中 `value` 支持以下类型:
+
+- 若为 `string` 类型,必须和 `format` 设置的格式对应;
+- 若为 `date` 对象类型,则可通过操作 `new Date()` 来对选项值进行相应的返回计算;
+- 若为 `array` 类型,则数组成员可填写开始日期和结束日期。
+- 若为 `function` 类型,返回值同上。2.8.16+
+
+详细用法可参考: [#示例](#demo-shortcut)
+
+
+string date array function
+-
+
+
+weekStart 2.7+
+
+
+设置起始周。 支持 0-6 的数字,`0` 即代表从周日开始。
+
+```
+weekStart: 1 // 设置周一为起始周
+```
+
+
+number
+
+
+`0`
+
+
+
+
+isPreview
+
+
+用于是否在面板左下角显示当前结果的预览。当 `type:datetime` 时强制为 `false`。
+
+
+boolean
+
+
+`true`
+
+
+
+
+
+
+[min / max](#options.minmax)
+
+
+
+
+
+
+限制可供选择的最小或最大日期时间值。默认值:
+
+- `min: '1900-1-1'`
+- `max: '2099-12-31'`
+
+
+
+属性值支持以下可选类型:
+
+- 若值为字符类型,则:年月日必须用 `-` 连接,且时分秒必须用 `:` 连接。 此处无需遵循 `format` 设定的格式;
+- 若值为整数类型,且数字 < 86400000,则数字代表天数,如: `min: -7` 即代表最小日期在 7 天前,正数代表若干天后;
+- 若值为整数类型,且数字 ≥ 86400000,则数字代表毫秒数,如:`max: 4073558400000` 即代表最大日期在公元 3000年1月1日。
+
+示例:
+
+```
+min: '2017-1-1 00:00:00' // 最小日期时间值
+min: -7 // 最小日期为 7 天前
+max: 7 // 最大日期为 7 天后
+```
+
+相关效果可参考: [#示例](#demo-limit)
+
+
+
+
+disabledDate 2.9.8+
+
+
+用于设置不可选取的日期。示例:
+
+```js
+disabledDate: function(date, type){
+ // date - 当前的日期对象
+ // type - 面板类型,'start'/'end'
+
+ // 返回值为 true 的日期会被禁用
+ return date.getTime() < new Date(2024, 1).getTime(); // 2024-02-01
+}
+
+```
+
+
+function
+ -
+
+
+disabledTime 2.9.8+
+
+
+用于设置不可选取的时间。示例:
+
+```js
+disabledTime: function(date, type){
+ // date - 当前的日期对象
+ // type - 面板类型,'start'/'end'
+
+ // 数组中指定的时间会被禁用
+ return {
+ hours: function(){
+ return range(0, 10);
+ },
+ minutes:function(hour){
+ return hour > 5 ? range(0, 20) : [];
+ },
+ seconds:function(hour, minute){
+ return range(0, 2);
+ }
+ };
+}
+
+function range(start, end) {
+ var result = [];
+ for (var i = start; i < end; i++) {
+ result.push(i);
+ }
+ return result;
+}
+
+```
+
+
+function
+ -
+
+
+trigger
+
+
+自定义弹出组件面板的事件
+
+
+string
+
+
+`click`
+
+
+
+
+show
+
+
+是否在渲染时默认显示组件面板。组件在执行渲染时,默认需通过触发目标元素的事件,方可显示组件面板,而该属性可跳过目标元素的事件,直接显示组件面板。
+
+
+boolean
+
+
+`false`
+
+
+
+
+position
+
+
+设置组件面板的定位方式。支持以下可选值:
+
+- `absolute` 绝对定位,始终吸附在绑定元素周围。
+- `fixed` 固定定位,初始吸附在绑定元素周围,不随浏览器滚动条所左右。一般用于在固定定位的弹层中使用。
+- `static` 静态定位,控件将直接嵌套显示在指定容器中。用法详见:[#示例](#demo-static)
+
+
+string
+
+
+`absolute`
+
+
+
+
+zIndex
+
+
+设置组件面板的层叠顺序。一般用于解决与其它元素的互相被遮掩的问题。若 `position: 'static'` 时,则该属性无效。
+
+
+number
+
+
+`99999999`
+
+
+
+
+
+
+[shade](#options.shade) 2.8+
+
+
+
+
+用于开启弹出日期面板时的遮罩。值支持以下可选类型:
+
+
+- 若为 `number` 类型,则表示遮罩透明度。如:
+
+```
+shade: 0.5
+```
+
+- 若为 `array` 类型,则可设置遮罩颜色和透明度,如:
+
+```
+shade: [0.5, '#000'] // 遮罩的透明度和背景色
+```
+
+效果详见: [#示例](#demo-more)
+
+
+number array
+-
+
+
+showBottom
+
+
+是否显示组件面板的底部栏
+
+
+boolean
+
+
+`true`
+
+
+
+
+btns
+
+
+自定义排版组件面板底部栏中的按钮,按钮将按照数组顺序排列。内置按钮名称:`clear,now,confirm` 。
+
+```
+ // 显示清空、确认按钮
+btns: ['clear', 'confirm']
+```
+
+
+array
+-
+
+
+autoConfirm 2.8+
+
+
+是否在选中目标值时即自动确认。
+ 当开启 `range` 属性时,该属性无效。
+
+
+boolean
+
+
+`true`
+
+
+
+
+lang
+
+
+设置组件的语言版本。可选值如下:
+
+- `cn` 中文版
+- `en` 英文版
+
+
+string
+
+
+`cn`
+
+
+
+
+
+
+[theme](#options.theme)
+
+
+
+
+
+
+设置组件面板主题。除了默认主题,还内置主题: `molv` `grid` `circle`2.8+ ,且支持直接传入自定义的主题色。
+
+
+
+```
+theme: '#FF5722'
+```
+
+注 2.8+ : 多个主题可用数组格式,如:
+
+```
+theme: ['grid', '#FF5722']
+```
+
+若第 1 个成员为 hex 格式的主色值,则第 2 个成员为辅色值
+
+```
+// 主色、辅色 --- 2.8.4 新增
+theme: ['#16baaa', '#16b777']
+```
+
+效果及用法详见: [#示例](#demo-theme)
+
+
+string array
+-
+
+
+calendar
+
+
+是否显示我国常见的公历节日。当 `lang: 'en'` 时无效。
+
+
+boolean
+
+
+`true`
+
+
+
+
+
+
+[mark](#options.mark)
+
+
+
+
+
+
+自定义日期标记。该属性是对 `calendar` 属性的进一步延伸,灵活度更高。属性可批量设置多个日期标记,如:
+
+
+
+- object 类型
+
+```
+mark: {
+ '0-10-14': '生日', //每年每月的某一天
+ '0-0-10': '工资', // 每月 10 号
+ '2008-8-8': '开幕', // 指定的日期
+}
+```
+
+前缀 `0-` 即代表每年,`0-0-` 即代表每年每月。
+
+- function 类型 2.9.9+
+
+```
+mark: function (ymd, render) {
+ var y = ymd.year;
+ var m = ymd.month;
+ var d = ymd.date;
+
+ // 字符串
+ if (m === 6 && d === 1) return render('儿童节');
+
+ // 对象
+ render ({
+ '0-10-14': '生日',
+ '0-0-15': '中旬',
+ '2024-03-20': 'v2',
+ '2024-03-31': '月底',
+ });
+}
+```
+
+效果详见: [#示例](#demo-mark)
+
+
+
+object
+-
+
+
+
+
+[holidays](#options.holidays) 2.7+
+
+
+
+
+
+用于标注节假日及补班日。
+
+
+- 若为 array 类型,值是一个二维数组,如:
+
+```
+holidays: [
+ // 2023 年的节假日
+ ['2023-1-1','2023-1-2','2023-1-3'],
+ // 2023 年的补班日
+ ['2023-1-28','2023-1-29']
+]
+```
+
+- 若为 function 类型 2.9.9+
+
+```
+holidays: function (ymd, render) {
+ var y = ymd.year;
+ var m = ymd.month;
+ var d = ymd.date;
+
+ // 字符串
+ if (y === 2023 && m === 6) {
+ render('holidays'); // 'holidays'/'workdays'
+ // 数组
+ } else if (y === 2024) {
+ render([
+ ['2024-03-01', '2024-03-02', '2024-03-03'],
+ ['2024-03-6', '2024-03-25'],
+ ]);
+ }
+}
+```
+
+相关日期值可详细参考国家每年公布的法定节假日安排
+
+效果详见: [#示例](#demo-mark)
+
+
+array
+-
+
+
+cellRender 2.9.9+
+
+
+自定义单元格内容。
+
+```
+cellRender: function(ymd, render, info){
+ var y = ymd.year;
+ var m = ymd.month;
+ var d = ymd.date;
+
+ // 面板类型 'year' | 'month' | 'date'
+ if(info.type === 'date'){
+ render(d); // 参数为 string, HTMLElement, JQuery 类型
+ }
+}
+```
+
+
+function
+ -
+
+
+
+
+
+
+
+[回调函数](#options.callback)
+
+
+
+
+
+
+
+
+[ready](#options.ready)
+
+
+
+
+
+组件面板初始打开的回调函数。返回的参数如下:
+
+
+```
+ready: function(date){
+ /* 得到初始的日期时间对象,date 参数格式如下:
+ {
+ year: 2017, // 年
+ month: 8, // 月
+ date: 18, // 日
+ hours: 0, // 时
+ minutes: 0, // 分
+ seconds: 0 // 秒
+ }
+ */
+ console.log(date);
+}
+```
+
+
+
+
+
+
+[change](#options.change)
+
+
+
+
+
+日期时间被切换后的回调函数。返回的参数如下:
+
+
+```
+change: function(value, date, endDate){
+ console.log(value); // 日期字符,如: 2017-08-18
+ console.log(date); // 包含年月日时分秒各项值的对象
+ console.log(endDate); // 结束日期时间对象,当设置 range 时才会返回。对象成员同上。
+}
+```
+
+
+
+
+
+
+[done](#options.done)
+
+
+
+
+
+日期时间选择完毕的回调函数,点击清空、现在、确定也均会触发。返回的参数如下:
+
+
+```
+done: function(value, date, endDate){
+ console.log(value); // 日期字符,如: 2017-08-18
+ console.log(date); // 包含年月日时分秒各项值的对象
+ console.log(endDate); // 结束日期时间对象,当设置 range 时才会返回。对象成员同上。
+}
+```
+
+
+
+
+onConfirm 2.8+
+
+
+点击底部栏「确定」按钮时的回调函数。返回的参数同 `done`。
+
+
+
+
+onNow 2.8+
+
+
+点击底部栏「现在」按钮时的回调函数。返回的参数同 `done`。
+
+
+
+
+onClear 2.8+
+
+
+点击底部栏「清空」按钮时的回调函数。返回的参数同 `done`。
+
+
+
+
+close 2.7+
+
+
+组件面板被关闭(移除)后的回调函数。无返回参数。
+
+
+
+
+
+
diff --git a/docs/laydate/examples/cell.md b/docs/laydate/examples/cell.md
new file mode 100644
index 000000000..4c1bb6190
--- /dev/null
+++ b/docs/laydate/examples/cell.md
@@ -0,0 +1,188 @@
+
+
+
+
+
+
+ Document
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/laydate/examples/elem.md b/docs/laydate/examples/elem.md
new file mode 100644
index 000000000..46be4b909
--- /dev/null
+++ b/docs/laydate/examples/elem.md
@@ -0,0 +1,25 @@
+
+
+
+
diff --git a/docs/laydate/examples/format.md b/docs/laydate/examples/format.md
new file mode 100644
index 000000000..2c4351cd9
--- /dev/null
+++ b/docs/laydate/examples/format.md
@@ -0,0 +1,78 @@
+
+
+
+
diff --git a/docs/laydate/examples/limit.md b/docs/laydate/examples/limit.md
new file mode 100644
index 000000000..c5dde7c93
--- /dev/null
+++ b/docs/laydate/examples/limit.md
@@ -0,0 +1,106 @@
+
+
+
+
diff --git a/docs/laydate/examples/mark.md b/docs/laydate/examples/mark.md
new file mode 100644
index 000000000..7d4514bf3
--- /dev/null
+++ b/docs/laydate/examples/mark.md
@@ -0,0 +1,66 @@
+
+
+
+
diff --git a/docs/laydate/examples/more.md b/docs/laydate/examples/more.md
new file mode 100644
index 000000000..0f8ed575a
--- /dev/null
+++ b/docs/laydate/examples/more.md
@@ -0,0 +1,201 @@
+
+
+ 覆盖实例与解除实例 2.8+ :
+
+
+
+
+
+
diff --git a/docs/laydate/examples/normal.md b/docs/laydate/examples/normal.md
new file mode 100644
index 000000000..f334b92fc
--- /dev/null
+++ b/docs/laydate/examples/normal.md
@@ -0,0 +1,33 @@
+
+
+
+
diff --git a/docs/laydate/examples/range.md b/docs/laydate/examples/range.md
new file mode 100644
index 000000000..b1e8b2d7f
--- /dev/null
+++ b/docs/laydate/examples/range.md
@@ -0,0 +1,111 @@
+
+
+
+
diff --git a/docs/laydate/examples/shortcut.md b/docs/laydate/examples/shortcut.md
new file mode 100644
index 000000000..53c09b17f
--- /dev/null
+++ b/docs/laydate/examples/shortcut.md
@@ -0,0 +1,559 @@
+
+
+
+
+
diff --git a/docs/laydate/examples/static.md b/docs/laydate/examples/static.md
new file mode 100644
index 000000000..371c0f660
--- /dev/null
+++ b/docs/laydate/examples/static.md
@@ -0,0 +1,34 @@
+
+
+
+
diff --git a/docs/laydate/examples/theme.md b/docs/laydate/examples/theme.md
new file mode 100644
index 000000000..750c28eb8
--- /dev/null
+++ b/docs/laydate/examples/theme.md
@@ -0,0 +1,73 @@
+
+
+
+
diff --git a/docs/laydate/examples/type.md b/docs/laydate/examples/type.md
new file mode 100644
index 000000000..1a33aee35
--- /dev/null
+++ b/docs/laydate/examples/type.md
@@ -0,0 +1,78 @@
+
+
+
+
diff --git a/docs/laydate/index.md b/docs/laydate/index.md
new file mode 100644
index 000000000..a7b24f1d5
--- /dev/null
+++ b/docs/laydate/index.md
@@ -0,0 +1,186 @@
+---
+title: 日期与时间选择器 laydate
+toc: true
+---
+
+# 日期与时间选择器
+
+> 日期与时间选择器 `laydate` 提供了年、月、日、时、分、秒的多类型选择面板,也是 Layui 的常用组件之一。
+
+示例
+
+
+
+
+{{- d.include("/laydate/detail/demo.md") }}
+
+
+
+
+API
+
+| API | 描述 |
+| --- | --- |
+| var laydate = layui.laydate | 获得 `laydate` 模块。 |
+| [laydate.render(options)](#render) | laydate 组件渲染,核心方法。 |
+| [laydate.hint(id, opts)](#hint) 2.8+ | 在对应的 laydate 组件面板上弹出提示层。 |
+| [laydate.getInst(id)](#getInst) 2.8+ | 获取组件对应的渲染实例。 |
+| [laydate.unbind(id)](#unbind) 2.8+ | 对目标元素解除当前实例的绑定。 |
+| [laydate.close(id)](#close) 2.7+ | 关闭日期面板。 |
+| [laydate.getEndDate(month, year)](#getEndDate) | 获取某月的最后一天。 |
+
+渲染
+
+`laydate.render(options);`
+
+- 参数 `options` : 基础属性选项。[#详见属性](#options)
+ 注 2.8+ : 除 `elem` 属性外,其他基础属性也可以直接写在元素的 `lay-options="{}"` 属性中。
+
+```
+
+
+
+
+
+
+```
+
+属性
+
+
+{{- d.include("/laydate/detail/options.md") }}
+
+
+弹出提示 2.8+
+
+`laydate.hint(id, opts);`
+
+- 参数 `id` : 组件渲染时定义的 `id` 属性值
+- 参数 `opts` : 该方法支持的属性选项,详见下表
+
+| opts | 描述 | 类型 | 默认值 |
+| --- | --- | --- | --- |
+| content | 提示内容 | string | - |
+| ms | 提示层自动消失所需的毫秒数 | number | 3000 |
+
+该方法用于在指定的日期面板弹出一个提示层。
+
+```
+var laydate = layui.laydate;
+// 渲染
+laydate.render({
+ elem: '', // 绑定元素选择器
+ id: 'test', // 自定义 id
+ // 其他属性 …
+});
+// 弹出提示
+laydate.hint('test', {
+ content: '提示内容'
+});
+```
+
+获取实例 2.8+
+
+`laydate.getInst(id);`
+
+- 参数 `id` : 组件渲染时定义的 `id` 属性值
+
+该方法用于获取 laydate 对应 id 的渲染实例,以获得该实例对应的成员属性。
+
+```
+var laydate = layui.laydate;
+// 渲染
+laydate.render({
+ elem: '', // 绑定元素选择器
+ id: 'test', // 自定义 id
+ // 其他属性 …
+});
+// 获取对应的实例
+var inst = laydate.getInst('test');
+console.log(inst); // 实例对象
+```
+
+
+解除实例绑定 2.8+
+
+`laydate.unbind(id);`
+
+- 参数 `id` : 组件渲染时定义的 `id` 属性值
+
+该方法用于对目标元素对应的实例的绑定完全解除,即触发元素事件时,不再执行组件渲染。
+
+```
+var laydate = layui.laydate;
+// 渲染
+laydate.render({
+ elem: '', // 绑定元素选择器
+ id: 'test', // 自定义 id
+ // 其他属性 …
+});
+// 解除对应的实例绑定
+laydate.unbind('test');
+```
+
+
+关闭日期面板 2.7+
+
+`laydate.close(id);`
+
+- 参数 `id` : 组件渲染时定义的 `id` 属性值。 若 `id` 参数不填,则关闭当前打开的日期面板
+
+该方法用于关闭对应的日期面板
+
+```
+var laydate = layui.laydate;
+// 渲染
+laydate.render({
+ elem: '', // 绑定元素选择器
+ id: 'test', // 自定义 id
+ // 其他属性 …
+});
+// 关闭对应的日期面板
+laydate.close('test');
+```
+
+获取某月的最后一天
+
+`laydate.getEndDate(month, year);`
+
+- 参数 `month` : 月份,默认为当前月。
+- 参数 `year` : 年份,默认为今年。
+
+该方法用于获取某个月份的最后一天
+
+```
+var days1 = laydate.getEndDate(10); // 获得 10 月的最后一天为 31 号
+var days2 = laydate.getEndDate(2, 2080); // 获得 2080 年 2 月的最后一天为 29 号
+```
+
+## 贴士
+
+> laydate 曾经可作为单独组件使用,鉴于维护成本的考量,目前 laydate 组件已完全集成到 Layui 中,而单独版本已不做同步维护。
+因此,建议直接使用 layui 中 laydate 即可。
+
+
+
diff --git a/docs/layer/detail/demo.md b/docs/layer/detail/demo.md
new file mode 100644
index 000000000..2d81a5a32
--- /dev/null
+++ b/docs/layer/detail/demo.md
@@ -0,0 +1,110 @@
+在线测试
+
+
+
+{{- d.include("/layer/detail/run.md") }}
+
+
+
+
+
+弹层类型
+
+
+
+{{- d.include("/layer/examples/type.md") }}
+
+
+
+信息框
+
+信息框即 `dialog` 类型层,对应默认的 `type: 0`,该类型的弹层同时只能存在一个。更多说明详见:[#type](#options)
+
+
+
+{{- d.include("/layer/examples/alert.md") }}
+
+
+
+页面层
+
+
+
+{{- d.include("/layer/examples/page.md") }}
+
+
+
+iframe 层
+
+
+
+{{- d.include("/layer/examples/iframe.md") }}
+
+
+
+加载层
+
+为了不影响继续体验,以下每个 loading 示例均会在 3 秒后自动模拟关闭
+
+
+
+{{- d.include("/layer/examples/load.md") }}
+
+
+
+Tips 层
+
+
+
+{{- d.include("/layer/examples/tips.md") }}
+
+
+
+其他层
+
+
+
+{{- d.include("/layer/examples/other.md") }}
+
+
+
+更多演示
+
+
+
+{{- d.include("/layer/examples/offset.md") }}
+
+
+
+
+
+{{- d.include("/layer/examples/direction.md") }}
+
+
+
+
+
+{{- d.include("/layer/examples/more.md") }}
+
+
+
+
+
+{{- d.include("/layer/examples/btnasync.md") }}
+
+
+
+
+主题风格
+
+
+
+{{- d.include("/layer/examples/skin.md") }}
+
+
+
+
+### 小贴士
+
+> 事实上 layer 丰富的基础属性,可足够让您的弹出层变得千变万化,为了避免占用太多篇幅,就不做过多演示了。
+
diff --git a/docs/layer/detail/options.md b/docs/layer/detail/options.md
new file mode 100644
index 000000000..4e1f197e3
--- /dev/null
+++ b/docs/layer/detail/options.md
@@ -0,0 +1,965 @@
+
+
+
+
+
+
+
+
+
+ 属性名
+ 描述
+ 类型
+ 默认值
+
+
+
+
+type
+
+
+弹层类型。 可选值有:
+
+- `0` dialog 信息框(默认),*同时只能存在一个层*
+- `1` page 页面层,*可同时存在多个层*
+- `2` iframe 内联框架层,*可同时存在多个层*
+- `3` loading 加载层,*同时只能存在一个层*
+- `4` tips 贴士层,*可配置同时存在多个层*
+
+`layer` 弹层由以上 5 种类型构成。 不同的类型代表不同的弹出形态,`layer` 提供的所有的弹出方式均由此衍生。
+
+
+number
+
+
+`0`
+
+
+
+
+title
+
+
+弹层标题。其值支持以下可选类型:
+
+- 若为 `string` 类型 : 则表示为弹层的标题文本,如:
+
+```
+title: '标题'
+```
+
+- 若为 `array` 类型 : 则可设置标题文本和标题栏 CSS 样式:
+
+```
+ title: ['标题', 'font-size: 18px;']
+```
+
+- 若为 `boolean` 类型 : 则可设为 `false` 不显示标题栏。
+
+```
+title: false // 不显示标题栏
+```
+
+
+string array boolean
+
+
+`信息`
+
+
+
+
+
+
+[content](#options.content)
+
+
+
+
+
+
+弹层内容。 可传入的值比较灵活,支持以下使用场景:
+
+- 若 `type: 1`(页面层): 则 `content` 可传入值如下:
+
+```
+// 普通字符
+layer.open({
+ type: 1,
+ content: '传入任意文本或 HTML'
+});
+// 捕获页面已存在的 DOM 元素或 jQuery 对象
+layer.open({
+ type: 1,
+ content: $('#id') // 捕获层
+});
+```
+
+注意: 若采用捕获层,则捕获的元素必须存放在 `` 根节点下,否则可能被父级容器的相对定位所影响。
+
+
+
+- 若 `type: 2`(iframe 层): 则 `content` 可传入值如下:
+
+```
+// iframe URL
+layer.open({
+ type: 2,
+ content: 'http://cn.bing.com' // URL
+});
+// 是否屏蔽 iframe 滚动条
+layer.open({
+ type: 2,
+ // 数组第二个成员设为 no,即屏蔽 iframe 滚动条
+ content: ['http://cn.bing.com', 'yes']
+});
+```
+
+- 若为其他弹层类型,传入普通字符即可。
+
+相关效果可参考:[#示例](#demo-page)
+
+
+
+
+
+
+[area](#options.area)
+
+
+
+
+
+设置弹层的宽高,其值支持以下可选类型:
+
+
+- 若为 `array` 类型,则可同时设置宽高
+ - `area: ['520px', '320px']` 固定宽度和高度
+ - `area: ['auto', '320px']` 宽度自动,高度固定
+ - `area: ['520px', 'auto']` 宽度固定,高度自动
+- 若为 `string` 类型,则可定义宽度和宽高均自适应:
+ - `area: '520px'` 宽度固定,高度自适应
+ - `area: 'auto'` 宽度和高度均自适应
+
+
+array string
+
+
+`auto`
+
+
+
+
+maxWidth
+
+
+弹层的最大宽度。当 `area` 属性设置宽度自适应时有效。
+
+
+number
+
+
+`360`
+
+
+
+
+maxHeight
+
+
+弹层的最大高度。当 `area` 属性设置高度自适应时有效。
+
+
+number
+-
+
+
+
+
+[offset](#options.offset)
+
+
+
+
+
+弹层的偏移坐标。 支持以下可选值:
+
+
+- `offset: 'auto'` 坐标始终垂直水平居中
+- `offset: '16px'` 只设置垂直坐标,水平保持居中
+- `offset: ['16px', '16px']` 设置垂直和水平坐标
+- `offset: 't'` 上边缘
+- `offset: 'r'` 右边缘
+- `offset: 'b'` 下边缘
+- `offset: 'l'` 左边缘
+- `offset: 'rt'` 右上角
+- `offset: 'rb'` 右下角
+- `offset: 'lt'` 左上角
+- `offset: 'lb'` 左下角
+
+当设置边缘坐标时,可配合 `anim` 属性实现抽屉弹出效果。
+
+
+string array
+
+
+`auto`
+
+
+
+
+
+
+[anim](#options.anim)
+
+
+
+
+
+弹层的出场动画。支持以下可选值:
+
+
+- `anim: 0` 平滑放大。默认
+- `anim: 1` 从上掉落
+- `anim: 2` 从最底部往上滑入
+- `anim: 3` 从左滑入
+- `anim: 4` 从左翻滚
+- `anim: 5` 渐显
+- `anim: 6` 抖动
+
+边缘抽屉动画 2.8+ :
+
+- `anim: 'slideDown'` 从上边缘往下
+- `anim: 'slideLeft'` 从右边缘往左
+- `anim: 'slideUp'` 从下边缘往上
+- `anim: 'slideRight'` 从左边缘往右
+
+抽屉动画一般配合 `offset` 属性实现边缘弹出。[#详见示例](#demo-more)
+
+
+
+number string
+
+
+`0`
+
+
+
+
+isOutAnim
+
+
+是否开启弹层关闭时的动画。
+
+
+boolean
+
+
+`true`
+
+
+
+
+maxmin
+
+
+是否开启标题栏的最大化和最小化图标。
+
+
+boolean
+
+
+`false`
+
+
+
+
+
+
+[closeBtn](#options.closeBtn)
+
+
+
+
+
+是否开启标题栏的关闭图标,或设置关闭图标风格。
+
+
+- `closeBtn: 0` 不显示关闭图标
+- `closeBtn: 1` 关闭图标默认风格
+- `closeBtn: 2` 关闭图标风格二
+
+
+number
+
+
+`1`
+
+
+
+
+
+
+[icon](#options.icon)
+
+
+
+
+
+提示图标。 信息框和加载层的私有参数。
+
+
+- 若为信息框,支持传入 `0-6` 的可选值。 默认为 `-1`,即不显示图标。
+- 若为加载层,支持传入 `0-2` 的可选值
+
+```
+// eg1
+layer.alert('成功提示', {icon: 1});
+
+// eg2
+layer.msg('开心表情', {icon: 6});
+
+// eg3
+layer.load(1); // 加载层风格一
+```
+
+
+number
+
+
+`-1`
+
+
+
+
+
+
+[btn](#options.btn)
+
+
+
+
+
+自定义按钮。 页面层默认不开启。 按钮可无限数量,每一个按钮均会按照数组顺序生成对应的回调函数,如:
+
+
+```
+// eg1
+layer.confirm('询问框?', {
+ btn: ['按钮1', '按钮2', '按钮3']
+});
+// eg2
+layer.open({
+ content: 'test',
+ btn: ['按钮1', '按钮2', '按钮3'],
+ // 按钮1 的回调
+ btn1: function(index, layero, that){},
+ btn2: function(index, layero, that){
+ // 按钮2 的回调
+ // return false // 点击该按钮后不关闭弹层
+ },
+ btn3: function(index, layero, that){
+ // 按钮3 的回调
+ // return false // 点击该按钮后不关闭弹层
+ }
+});
+```
+
+
+string
+-
+
+
+
+
+[btnAlign](#options.btnAlign)
+
+
+
+
+
+按钮水平对其方式。支持以下可选值:
+
+
+- `btnAlign: 'l'` 按钮左对齐
+- `btnAlign: 'c'` 按钮水平居中对齐
+- `btnAlign: 'r'` 按钮右对齐。默认值,不用设置
+
+
+
+string
+
+
+`r`
+
+
+
+
+
+
+[btnAsync](#options.btnAsync) 2.9.12+
+
+
+
+
+
+
+异步按钮。开启之后,除 `layer.prompt` 的按钮外,按钮回调的返回值将支持 `boolean | Promise | JQueryDeferred` 类型,返回 `false` 或 `Promise.reject` 时阻止关闭。
+
+注意,此时 `yes` 和 `btn1`(两者等效) 回调的默认行为发生了变化,即由触发时不关闭弹层变为关闭弹层。
+
+
+
+```
+var sleep = function (time) {
+ return $.Deferred(function (defer) {
+ setTimeout(function () {
+ defer.resolve();
+ }, time)
+ })
+}
+// 下面以 confirm 层为例
+layer.confirm('一个询问框的示例?', {
+ btnAsync: true,
+ btn: ['确定', '关闭'] // 按钮
+ },
+ function (index, layero, that) {
+ var defer = $.Deferred();
+ // 注: that.loading() 仅 btnAsync 开启后支持,参数为 boolean 类型,表示打开或关闭按钮的加载效果。
+ that.loading(true);
+ sleep(1000).then(defer.resolve);
+ return defer.promise();
+ }
+);
+```
+
+
+boolean
+
+
+`false`
+
+
+
+
+
+
+[skin](#options.skin)
+
+
+
+
+
+弹层的主题风格。通过赋值对应的 className,实现对主题样式的定制。除了默认主题风格,还支持以下可选主题:
+
+
+- `lay-layer-molv` 墨绿主题
+- `lay-layer-lan` 深蓝主题
+- `lay-layer-win10` Windows 10 主题 2.8+
+
+还可传入其他任意 className 来自定义主题。 参考:[#示例](#demo-skin)
+
+
+
+string
+-
+
+
+
+
+[shade](#options.shade)
+
+
+
+
+
+弹层的遮罩。 支持以下写法:
+
+
+- `shade: 0.3` 设置遮罩深色背景的透明度
+- `shade: [0.3, '#FFF']` 设置遮罩透明度和颜色值
+- `shade: 0` 不显示遮罩
+
+
+number array
+
+
+`0.3`
+
+
+
+
+shadeClose
+
+
+是否点击遮罩时关闭弹层。当遮罩存在时有效。
+
+
+boolean
+
+
+`false`
+
+
+
+
+id
+
+
+弹层的唯一索引值。 一般用于页面层或 iframe 层弹出时的状态识别,设置该属性可防止弹层的重复弹出。
+
+
+string
+-
+
+
+hideOnClose 2.8.3+
+
+
+关闭弹层时,是否将弹层设置为隐藏状态(而非移除),当再次打开,直接显示原来的弹层。 若设为 `true`,则必须同时设置 `id` 属性方可有效。
+
+
+boolean
+
+
+`false`
+
+
+
+
+time
+
+
+弹层自动关闭所需的毫秒数。 如 `time: 3000` ,即代表 3 秒后自动关闭。 提示框、加载层、Tips 层三种弹出模式默认开启。
+
+
+number
+
+
+`0`
+
+
+
+
+fixed
+
+
+弹层是否固定定位,即始终显示在页面可视区域。
+
+
+boolean
+
+
+`true`
+
+
+
+
+zIndex
+
+
+弹层的初始层叠顺序值。
+
+
+number
+
+
+`19891014`
+
+
+
+
+resize
+
+
+是否允许拖拽弹层右下角拉伸尺寸。 该属性对加载层和 tips 层无效。
+
+
+boolean
+
+
+`true`
+
+
+
+
+scrollbar
+
+
+打开弹层时,是否允许浏览器出现滚动条。
+
+
+boolean
+
+
+`true`
+
+
+
+
+minStack 2.6+
+
+
+点击标题栏的最小化时,是否从页面左下角堆叠排列。
+
+
+boolean
+
+
+`true`
+
+
+
+
+removeFocus 2.8+
+
+
+是否移除弹层触发元素的焦点,避免按回车键时重复弹出。
+
+
+boolean
+
+
+`true`
+
+
+
+
+move
+
+
+绑定弹层的拖拽元素。 默认为触发弹层的标题栏进行拖拽。也可以设置 `move: false` 禁止拖拽。
+用法参考:[#示例](#demo-page)
+
+
+string DOM boolean
+-
+
+
+moveOut
+
+
+否允许拖拽到窗口外
+
+
+boolean
+
+
+`false`
+
+
+
+
+tips
+
+
+设置 tips 层的吸附位置和背景色,tips 层的私有属性。
+
+- 若为 `number` 类型,则支持 `1-4` 的可选值,分别代表*上右下左*的吸附位置。如: `tips: 1`
+- 若为 `array` 类型,则支持设置吸附位置和背景色,如:
+
+```
+tips: [1, '#000'] // 吸附在上的深色贴士层
+```
+
+
+number array
+
+
+`2`
+
+
+
+
+tipsMore
+
+
+是否允许同时存在多个 tips 层,即不销毁上一个 tips。
+
+
+boolean
+
+
+`false`
+
+
+
+
+
+
+
+
+
+[回调函数](#options.callback)
+
+
+
+
+
+
+
+
+[success](#options.success)
+
+
+
+
+
+打开弹层成功后的回调函数。返回的参数如下:
+
+
+```
+layer.open({
+ type: 1,
+ content: '内容',
+ success: function(layero, index, that){
+ // 弹层的最外层元素的 jQuery 对象
+ console.log(layero);
+ // 弹层的索引值
+ console.log(index);
+ // 弹层内部原型链中的 this --- 2.8+
+ console.log(that);
+ }
+});
+```
+
+
+
+
+
+
+[yes](#options.yes)
+
+
+
+
+
+
+点击「确定」按钮的回调函数。返回的参数同 `success`
+
+
+
+```
+layer.open({
+ content: '内容',
+ yes: function(index, layero, that){
+ // do something
+ layer.close(index); // 关闭弹层
+ }
+});
+```
+
+
+
+
+
+
+[cancel](#options.cancel)
+
+
+
+
+
+点击标题栏关闭按钮的回调函数。返回的参数同 `success`
+
+
+```
+layer.open({
+ content: '内容',
+ cancel: function(index, layero, that){
+ if(confirm('确定要关闭么')){
+ layer.close(index);
+ }
+ return false; // 阻止默认关闭行为
+ }
+});
+```
+
+
+
+
+
+
+[beforeEnd](#options.beforeEnd) 2.9.11+
+
+
+
+
+
+弹层被关闭前的回调函数。如果返回 false 或者 Promise.reject,将会取消关闭操作。
+
+
+```
+layer.open({
+ content: '
',
+ /** @type {(layero: JQuery, index: number) => boolean | JQueryDeferred | Promise} */
+ beforeEnd: function(layero, index, that){
+ return $.Deferred(function(defer){
+ var el = layero.find('#id');
+ var val = el.val().trim();
+ if(val){
+ layer.confirm('关闭后您填写的内容将不会得到保存,确定关闭吗?', function (i) {
+ layer.close(i);
+ defer.resolve(true)
+ });
+ }else{
+ defer.resolve(true)
+ }
+ }).promise();
+ }
+});
+```
+
+
+
+
+
+
+[end](#options.end)
+
+
+
+
+
+弹层被关闭且销毁后的回调函数。
+
+
+```
+layer.open({
+ content: '内容',
+ end: function(){
+ console.log('弹层已被移除');
+ }
+});
+```
+
+
+
+
+
+
+[moveEnd](#options.moveEnd)
+
+
+
+
+
+弹层拖拽完毕后的回调函数。
+
+
+```
+layer.open({
+ type: 1,
+ content: '内容',
+ moveEnd: function(layero){
+ console.log('拖拽完毕');
+ }
+});
+```
+
+
+
+
+
+
+[resizing](#options.resizing)
+
+
+
+
+
+弹层拉伸过程中的回调函数
+
+
+```
+layer.open({
+ type: 1,
+ content: '内容',
+ resizing: function(layero){
+ console.log('拉伸中');
+ }
+});
+```
+
+
+
+
+
+
+[full](#options.full)
+
+
+
+
+
+
+弹层最大化后的回调函数。返回的参数同 `success`
+
+
+
+```
+layer.open({
+ type: 1,
+ content: '内容',
+ full: function(layero, index, that){
+ console.log('弹层已最大化');
+ }
+});
+```
+
+
+
+
+
+
+[min](#options.min)
+
+
+
+
+
+
+弹层最小化后的回调函数。返回的参数同 `success`
+
+
+
+```
+layer.open({
+ type: 1,
+ content: '内容',
+ min: function(layero, index, that){
+ // do something
+ // return false; // 阻止默认最小化
+ }
+});
+```
+
+
+
+
+
+
+[restore](#options.restore)
+
+
+
+
+
+弹层被还原后的回调函数。返回的参数同 `success`
+
+
+```
+layer.open({
+ type: 1,
+ content: '内容',
+ restore: function(layero, index, that){
+ console.log('弹层已还原');
+ }
+});
+```
+
+
+
+
+
+
diff --git a/docs/layer/detail/run.md b/docs/layer/detail/run.md
new file mode 100644
index 000000000..df627586d
--- /dev/null
+++ b/docs/layer/detail/run.md
@@ -0,0 +1,35 @@
+
+
+
diff --git a/docs/layer/examples/alert.md b/docs/layer/examples/alert.md
new file mode 100644
index 000000000..4cec974e9
--- /dev/null
+++ b/docs/layer/examples/alert.md
@@ -0,0 +1,79 @@
+
+ 对话框带图标
+ 询问框
+ 深色提示框
+ 浅色提示框
+ 自定义按钮
+ 关闭倒计时
+
+
+
+
diff --git a/docs/layer/examples/btnasync.md b/docs/layer/examples/btnasync.md
new file mode 100644
index 000000000..d93c33206
--- /dev/null
+++ b/docs/layer/examples/btnasync.md
@@ -0,0 +1,90 @@
+alert
+confirm
+msg
+open
+prompt(不支持)
+
+
+
diff --git a/docs/layer/examples/direction.md b/docs/layer/examples/direction.md
new file mode 100644
index 000000000..a6ac10724
--- /dev/null
+++ b/docs/layer/examples/direction.md
@@ -0,0 +1,69 @@
+从页面四个边缘弹出(抽屉效果):
+
+
+ 从上往下
+ 从右往左
+ 从下往上
+ 从左往右
+
+
+
+
diff --git a/docs/layer/examples/iframe.md b/docs/layer/examples/iframe.md
new file mode 100644
index 000000000..f674ddd54
--- /dev/null
+++ b/docs/layer/examples/iframe.md
@@ -0,0 +1,76 @@
+
+
+ iframe 的父子操作
+
+
+ 弹出多媒体
+ 禁止 iframe 滚动条
+ 弹出任意 URL 页面
+
+
+
+
+
diff --git a/docs/layer/examples/load.md b/docs/layer/examples/load.md
new file mode 100644
index 000000000..4bf5444be
--- /dev/null
+++ b/docs/layer/examples/load.md
@@ -0,0 +1,49 @@
+
+ 风格1
+ 风格2
+ 风格3
+ 风格4
+
+
+
+
diff --git a/docs/layer/examples/more.md b/docs/layer/examples/more.md
new file mode 100644
index 000000000..28c9e0b49
--- /dev/null
+++ b/docs/layer/examples/more.md
@@ -0,0 +1,172 @@
+
+
+ 最大化弹出
+
+
+ 弹出时屏蔽浏览器滚动条
+
+
+ 页面锁屏
+
+
+ 自定义遮罩颜色和透明度
+
+
+ 多窗口模式 + 层叠置顶 + Esc 关闭
+
+
+
+
+
+
+
+
diff --git a/docs/layer/examples/offset.md b/docs/layer/examples/offset.md
new file mode 100644
index 000000000..7757f8e19
--- /dev/null
+++ b/docs/layer/examples/offset.md
@@ -0,0 +1,43 @@
+
+ 上
+ 右
+ 下
+ 左
+ 右上
+ 右下
+ 左下
+ 左上
+ 正中
+ 任意
+
+
+
+
diff --git a/docs/layer/examples/other.md b/docs/layer/examples/other.md
new file mode 100644
index 000000000..24d09e6f6
--- /dev/null
+++ b/docs/layer/examples/other.md
@@ -0,0 +1,102 @@
+
+ tab 层
+ prompt - 单行文本框层
+ prompt - 密令输入框层
+ prompt - 多行文本框层
+ photos - 单张图片层
+ photos - 多张相册层
+
+
+
+
+
diff --git a/docs/layer/examples/page.md b/docs/layer/examples/page.md
new file mode 100644
index 000000000..9a133f790
--- /dev/null
+++ b/docs/layer/examples/page.md
@@ -0,0 +1,151 @@
+
+ 普通页面层
+ 捕获层
+ 剔除默认标题栏
+ 绑定弹层的拖拽元素
+
+ 弹出任意自定义内容
+
+
+
+
+
+ 弹出已经存在于页面中的一段元素
+ 通常是放置在 <body> 根节点下
+
+
+
+
+
diff --git a/docs/layer/examples/skin.md b/docs/layer/examples/skin.md
new file mode 100644
index 000000000..99c4314dc
--- /dev/null
+++ b/docs/layer/examples/skin.md
@@ -0,0 +1,77 @@
+
+
+ 墨绿与深蓝主题
+
+
+ Windows 10 风格信息框
+
+
+ Win10 风格页面层
+
+ 自定义任意主题
+
+
+
+
+
+
diff --git a/docs/layer/examples/tips.md b/docs/layer/examples/tips.md
new file mode 100644
index 000000000..69a9f4b8e
--- /dev/null
+++ b/docs/layer/examples/tips.md
@@ -0,0 +1,48 @@
+
+ 显示在上
+ 显示在右
+ 显示在下
+ 显示在左
+ 自定义背景色
+ 允许多个 tips
+
+
+
+
diff --git a/docs/layer/examples/type.md b/docs/layer/examples/type.md
new file mode 100644
index 000000000..8fd630984
--- /dev/null
+++ b/docs/layer/examples/type.md
@@ -0,0 +1,106 @@
+
+ Alert
+ Confirm
+ Msg
+ Page
+ Iframe
+ Load
+ Tips
+ Prompt
+ Photots
+
+
+
+
+
diff --git a/docs/layer/index.md b/docs/layer/index.md
new file mode 100644
index 000000000..2369049e1
--- /dev/null
+++ b/docs/layer/index.md
@@ -0,0 +1,615 @@
+---
+title: 通用弹出层组件 layer
+toc: true
+---
+
+# 弹出层组件 🔥
+
+> 弹出层组件 `layer` 是 `Layui` 最古老的组件,也是使用覆盖面最广泛的代表性组件。 `layer` 集众多弹层功能为一体,灵活而多样,是许多开发者的网页弹出层的首选交互方案,在各类业务场景都能发挥重要作用。
+
+
+示例
+
+点击下述按钮,查看每个示例对应的弹层效果。
+
+
+{{- d.include("/layer/detail/demo.md") }}
+
+
+API
+
+| API | 描述 |
+| --- | --- |
+| var layer = layui.layer | 获得 `layer` 模块。 |
+| 弹出 : | - |
+| [layer.open(options)](#open) | 打开弹层,核心方法。下述所有弹出方式均为该方法的二次封装 |
+| [layer.alert(content, options, yes)](#alert) | 弹出 `dialog` 类型信息框。 |
+| [layer.confirm(content, options, yes, cancel)](#confirm) | 弹出 `dialog` 类型询问框。 |
+| [layer.msg(content, options, end)](#msg) | 弹出 `dialog` 类型提示框。 |
+| [layer.load(icon, options)](#load) | 弹出 `loading` 类型加载层。 |
+| [layer.tips(content, elem, options)](#tips) | 弹出 `tips` 类型贴士层。 |
+| [layer.prompt(options, yes)](#prompt) | 弹出 `page` 类型输入框层。 |
+| [layer.photos(options)](#photos) | 弹出 `page` 类型图片层。 |
+| [layer.tab(options)](#tab) | 弹出 `page` 类型标签页层。 |
+| 关闭 : | - |
+| [layer.close(index, callback)](#close) | 关闭对应的层,核心方法。 |
+| [layer.closeAll(type, callback)](#closeAll) | 关闭所有对应类型的层。 |
+| [layer.closeLast(type, callback)](#closeLast) 2.8+ | 关闭最近打开的对应类型的层。 |
+| 其他 : | - |
+| [layer.config(options)](#config) | 全局配置默认属性。 |
+| [layer.ready(callback)](#ready) | 样式初始化就绪。 |
+| [layer.style(index, css)](#set-style) | 重新设置弹层样式。 |
+| [layer.title(title, index)](#set-title) | 设置弹层的标题。 |
+| [layer.getChildFrame(selector, index)](#getChildFrame) | 获取 iframe 页中的元素。 |
+| [layer.getFrameIndex(window.name)](#getFrameIndex) | 在 iframe 页中获取弹层索引。 |
+| [layer.iframeAuto(index)](#iframeAuto) | 设置 iframe 层高度自适应。 |
+| [layer.iframeSrc(index, url)](#iframeSrc) | 重新设置 iframe 层 URL。 |
+| layer.index | 获取最新弹出层的索引 |
+| layer.zIndex | 获取最新弹出层的层叠顺序 |
+| [layer.setTop(layero)](#setTop) | 将对应弹层的层叠顺序为置顶。 |
+| [layer.full(index)](#full) | 设置弹层最大化尺寸。 |
+| [layer.min(index)](#min) | 设置弹层最小化尺寸。 |
+| [layer.restore(index)](#restore) | 还原弹层尺寸。 |
+
+
+打开弹层
+
+`layer.open(options);`
+
+- 参数 `options` : 基础属性选项。[#详见属性](#options)
+
+打开弹层的核心方法,其他不同类型的弹出方法均为该方法的二次封装。
+
+```
+// 该方法返回当前层的唯一索引,以便其他方法对该弹层进行相关操作
+var index = layer.open({
+ type: 1, // page 层类型,其他类型详见「基础属性」
+ content: 'test
'
+});
+```
+
+基础属性
+
+
+{{- d.include("/layer/detail/options.md") }}
+
+
+弹出信息框
+
+`layer.alert(content, options, yes);`
+
+- 参数 `content` : 弹出内容
+- 参数 `options` : 基础属性选项。[#详见属性](#options)
+- 参数 `yes` : 点击确定后的回调函数
+
+该方法用于弹出 `dialog` 类型信息框(`type: 0`),参数自动向左补位。
+
+```
+// eg1
+layer.alert('一个简单的信息框');
+// eg2
+layer.alert('开启图标', {icon: 1}, function(index){
+ // do something
+ // …
+ layer.close(index);
+});
+// eg3
+layer.alert('不开启图标', function(index){
+ // do something
+ // …
+ layer.close(index);
+});
+```
+
+弹出询问框
+
+`layer.confirm(content, options, yes, cancel);`
+
+- 参数 `content` : 弹出内容
+- 参数 `options` : 基础属性选项。[#详见属性](#options)
+- 参数 `yes` : 点击确定后的回调函数
+- 参数 `cancel` : 点击第二个按钮(默认「取消」)后的回调函数
+
+该方法用于弹出 `dialog` 类型询问框(`type: 0`),参数自动向左补位。
+
+```
+// eg1
+layer.confirm('确定吗?', {icon: 3, title:'提示'}, function(index){
+ // do something
+ // …
+ layer.close(index);
+});
+// eg2
+layer.confirm('确定吗?', function(index){
+ // do something
+ // …
+ layer.close(index);
+});
+```
+
+
+弹出提示框
+
+`layer.msg(content, options, end);`
+
+- 参数 `content` : 弹出内容
+- 参数 `options` : 基础属性选项。[#详见属性](#options)
+- 参数 `end` : 提示框关闭后的回调函数
+
+该方法用于弹出 `dialog` 类型提示框(`type: 0`),默认 `3` 秒后自动关闭。参数自动向左补位。
+
+```
+// eg1
+layer.msg('普通提示');
+// eg2
+layer.msg('带 icon 的提示', {icon: 6});
+// eg3
+layer.msg('关闭后想做些什么', function(){
+ // do something
+});
+// eg
+layer.msg('提示框', {
+ icon: 1,
+ time: 2000 // 设置 2 秒后自动关闭
+}, function(){
+ // do something
+});
+```
+
+
+弹出加载层
+
+`layer.load(icon, options);`
+
+- 参数 `icon` : 加载图标风格,支持 `0-2` 可选值
+- 参数 `options` : 基础属性选项。[#详见属性](#options)
+
+该方法用于弹出 `load` 类型加载层(`type: 3`)。
+
+```
+// eg1
+var index = layer.load(); // 默认加载图标风格
+// eg2
+var index = layer.load(1); // 加载图标风格 1
+// eg3
+var index = layer.load(2, {time: 10*1000}); // 加载图标风格,并设置最长等待 10 秒
+
+// 关闭加载层
+layer.close(index);
+```
+
+弹出贴士层
+
+`layer.tips(content, elem, options);`
+
+- 参数 `content` : 弹出内容
+- 参数 `elem` : 吸附的目标元素选择器或对象
+- 参数 `options` : 基础属性选项。[#详见属性](#options)
+
+该方法用于弹出 `tips` 类型贴士层(`type: 4`),默认 `3` 秒后自动关闭。
+
+```
+// eg1
+layer.tips('小贴士', '#id');
+// eg2
+$('#id').on('click', function(){
+ var elem = this;
+ layer.tips('小贴士', elem); //在元素的事件回调体中,follow直接赋予this即可
+});
+// eg3
+layer.tips('显示在目标元素上方', '#id', {
+ tips: 1 // 支持 1-4 可选值,更多详见基础属性中的 tips 介绍
+});
+```
+
+弹出输入框
+
+`layer.prompt(options, yes);`
+
+- 参数 `options` : 基础属性选项。除了支持 [基础属性](#options) 之外,还支持下表私有属性:
+
+| 私有属性 | 描述 | 类型 | 默认值 |
+| --- | --- | --- | --- |
+| formType | 输入框类型。支持以下可选值: | number/string | `0` |
+| value | 输入框初始值 | string | - |
+| maxlength | 可输入的最大字符长度 | number | `500` |
+| placeholder | 输入框内容为空时的占位符 | string | - |
+
+
+- 参数 `yes` : 点击确定后的回调函数
+
+该方法用于弹出输入框层,基于 `type: 1`(即 `page` 层)的自定义内容。 效果参考: [#示例](#demo-other)
+
+```
+// eg1
+layer.prompt(function(value, index, elem){
+ alert(value); // 得到 value
+ layer.close(index); // 关闭层
+});
+
+// eg2
+layer.prompt({
+ formType: 2,
+ value: '初始值',
+ title: '请输入值',
+ area: ['800px', '350px'] // 自定义文本域宽高
+}, function(value, index, elem){
+ alert(value); // 得到 value
+ layer.close(index); // 关闭层
+});
+```
+
+弹出图片层
+
+`layer.photos(options);`
+
+- 参数 `options` : 基础属性选项。除了支持 [基础属性](#options) 之外,还支持下表私有属性:
+
+| 私有属性 | 描述 | 类型 | 默认值 |
+| --- | --- | --- | --- |
+| photos | 图片层的数据源,格式详见下述示例。 | object | - |
+| toolbar 2.8.16+ | 是否显示顶部工具栏 | boolean | `true` |
+| footer 2.8.16+ | 是否隐藏底部栏 | boolean | `true` |
+| tab | 图片层切换后的回调函数,返回的参数见下述示例 | function | - |
+
+该方法用于弹出图片层,基于 `type: 1`(即 `page` 层)的自定义内容。
+
+**用法一:直接赋值图片数据**。 效果参考: [#示例](#demo-other)
+
+```
+layer.photos({
+ photos: { // 图片层的数据源
+ "title": "", // 相册标题
+ "id": 123, // 相册 id
+ "start": 0, // 初始显示的图片序号,默认 0
+ "data": [ // 相册包含的图片,数组格式
+ {
+ "alt": "图片名",
+ "pid": 666, // 图片id
+ "src": "", // 原图地址
+ "thumb": "" // 缩略图地址
+ },
+ // …
+ ]
+ },
+ tab: function(data, layero){ // 图片层切换后的回调
+ console.log(data); // 当前图片数据信息
+ console.log(layero); // 图片层的容器对象
+ }
+});
+```
+
+**用法二:绑定页面图片元素**。点击图片时,弹出对应的图片层。
+
+
+
+
+
+
+
+
+
+
+
+
+
+弹出标签层
+
+`layer.tab(options);`
+
+- 参数 `options` : 基础属性选项。除了支持 [基础属性](#options) 之外,还支持下表私有属性:
+
+| 私有属性 | 描述 | 类型 | 默认值 |
+| --- | --- | --- | --- |
+| tab | 标签层的数据源,格式详见下述示例。 | array | - |
+
+该方法用于弹出标签层,基于 `type: 1`(即 `page` 层)的自定义内容。 效果参考: [#示例](#demo-other)
+
+```
+layer.tab({
+ area: ['600px', '300px'],
+ tab: [{ // 标签层的数据源
+ title: '标题 1',
+ content: '内容 1'
+ }, {
+ title: '标题 2',
+ content: '内容 2'
+ }, {
+ title: '标题 3',
+ content: '内容 3'
+ }]
+});
+```
+
+
+关闭弹层
+
+`layer.close(index, callback);`
+
+- 参数 `index` : 打开弹层时返回的唯一索引
+- 参数 `callback` : 关闭弹层后的回调函数
+
+该方法用于关闭对应的弹层。
+
+```
+// 每一种弹层调用方式,都会返回一个 index
+var index1 = layer.open();
+var index2 = layer.alert();
+var index3 = layer.load();
+var index4 = layer.tips();
+
+// 关闭对应的弹层
+layer.close(index1);
+```
+
+在 iframe 弹层页面中关闭自身
+
+```
+var index = parent.layer.getFrameIndex(window.name); // 先得到当前 iframe 层的索引
+parent.layer.close(index); // 再执行关闭
+```
+
+
+关闭所有层
+
+`layer.closeAll(type, callback);`
+
+- 参数 `type` : 弹层的类型。可选值:`dialog,page,iframe,loading,tips`
+- 参数 `callback` : 关闭弹层后的回调函数
+
+该方法用于关闭所有同类型的弹层。
+
+```
+layer.closeAll(); // 关闭所有类型的层
+layer.closeAll('dialog'); // 关闭所有的信息框
+layer.closeAll('page'); // 关闭所有的页面层
+layer.closeAll('iframe'); // 关闭所有的 iframe 层
+layer.closeAll('loading'); // 关闭所有的加载层
+layer.closeAll('tips'); // 关闭所有的 tips 层
+```
+
+关闭最近一次打开的层 2.8+
+
+`layer.closeLast(type, callback);`
+
+- 参数 `type` : 弹层的类型。可选值:`dialog,page,iframe,loading,tips`
+- 参数 `callback` 2.9+ : 关闭弹层后的回调函数
+
+该方法用于关闭最近一次打开的对应类型的层。
+
+```
+layer.closeLast('dialog'); // 关闭最近一次打开的信息框
+layer.closeLast('page'); // 关闭最近一次打开的页面层
+layer.closeLast('iframe'); // 关闭最近一次打开的 iframe 层
+layer.closeLast('loading'); // 关闭最近一次打开的加载层
+layer.closeLast('tips'); // 关闭最近一次打开的 tips 层
+layer.closeLast(['dialog', 'page']); // 关闭最近一次打开的信息框或页面层,2.9.7+
+```
+
+全局配置默认属性
+
+`layer.config(options);`
+
+- 参数 `options` : 基础属性选项。[#详见属性](#options)
+
+该方法用于全局设置弹层的默认基础属性。
+
+```
+layer.config({
+ title: '默认标题',
+ skin: '', // 设置默认主题
+ // … 其他任意基础属性
+})
+```
+
+样式初始化就绪
+
+`layer.ready(callback);`
+
+- 参数 `callback` : 初始化完毕后的回调函数
+
+该方法一般是在源码方式引入 `layui.js`,且要在页面初始即弹出层时使用,以确保弹层所依赖的样式文件先行加载。 而引入 release 版的 `layui.js` 则无需使用该方法,因为弹层样式已经统一合并到 `layui.css` 中。
+
+```
+// 页面初始弹出层
+layer.ready(function(){
+ layer.alert('对话框内容');
+});
+```
+
+重新设置弹层样式
+
+`layer.style(index, css);`
+
+- 参数 `index` : 打开弹层时返回的唯一索引
+- 参数 `css` : 要设置的 `css` 属性
+
+该方法对 `loading` 层和 `tips` 层无效。
+
+```
+// 打开弹层
+var index = layer.open({
+ type: 1,
+ content: '内容'
+});
+
+// 重新给对应层设定 width、top 等
+layer.style(index, {
+ width: '1000px',
+ top: '10px'
+});
+```
+
+设置弹层的标题
+
+`layer.title(title, index);`
+
+- 参数 `title` : 标题
+- 参数 `index` : 打开弹层时返回的唯一索引
+
+```
+// 打开弹层
+var index = layer.open({
+ type: 1,
+ content: '内容'
+});
+
+// 重新设置标题
+layer.title('新标题', index)
+```
+
+获取 iframe 页中的元素
+
+`layer.getChildFrame(selector, index);`
+
+- 参数 `selector` : iframe 子页面的选择器或元素对象
+- 参数 `index` : 打开弹层时返回的唯一索引
+
+该方法用于在父页面获取 iframe 子页面中的元素
+
+```
+layer.open({
+ type: 2, // iframe 层
+ content: '/layer/test/iframe.html',
+ success: function(layero, index){
+ // 获取 iframe 中 body 元素的 jQuery 对象
+ var body = layer.getChildFrame('body', index);
+ // 给 iframe 页中的某个输入框赋值
+ body.find('input').val('Hello layer.');
+ }
+});
+```
+
+在 iframe 页中获取弹层索引
+
+`layer.getFrameIndex(window.name);`
+
+- 参数 `window.name` : 当前 iframe 窗口的 `name` 属性值
+
+该方法用于在 iframe 页面内部获取当前 iframe 弹层的索引,以便关闭自身。
+
+```
+var index = parent.layer.getFrameIndex(window.name); // 获取当前 iframe 层的索引
+parent.layer.close(index); // 关闭当前 iframe 弹层
+```
+
+设置 iframe 层高度自适应
+
+`layer.iframeAuto(index);`
+
+- 参数 `index` : 打开弹层时返回的唯一索引
+
+该方法可让 iframe 高度跟随内容自适应
+
+```
+layer.open({
+ type: 2, // iframe 层
+ content: '/layer/test/iframe.html',
+ area: '600px', // 弹层初始宽度
+ success: function(layero, index, that){
+ layer.iframeAuto(index); // 让 iframe 高度自适应
+ that.offset(); // 重新自适应弹层坐标
+ }
+});
+```
+
+重新设置 iframe 层 URL
+
+`layer.iframeSrc(index, url);`
+
+- 参数 `index` : 打开弹层时返回的唯一索引
+- 参数 `url` : URL 地址
+
+```
+// 打开弹层
+var index = layer.open({
+ type: 2, // iframe 层
+ content: '/layer/test/iframe.html'
+});
+// 重置 iframe 页面 URL
+layer.iframeSrc(index, 'https://cn.bing.com/');
+```
+
+置顶弹层
+
+`layer.setTop(layero);`
+
+- 参数 `layero` : layer 最外层容器的元素对象,一般可通过各个回调函数返回的参数获取。
+
+该方法一般用于多弹层模式时,实现点击某个弹层让其层叠顺序置顶。效果参考:[#示例](#demo-more)
+
+```
+// 多弹层模式的层叠顺序置顶
+layer.open({
+ type: 1, // 页面层
+ shade: false,
+ area: ['520px', '320px'],
+ maxmin: true,
+ content: '多弹层模式的层叠顺序置顶
',
+ zIndex: layer.zIndex, // 重点 1 --- 初始设置当前最高层叠顺序,
+ success: function(layero){
+ layer.setTop(layero); // 重点 2 --- 保持选中窗口置顶
+ }
+});
+```
+
+设置弹层最大化
+
+`layer.full(index);`
+
+- 参数 `index` : 打开弹层时返回的唯一索引
+
+```
+// 打开弹窗
+var index = layer.open({
+ type: 1, // 页面层
+ content: '弹层内容'
+});
+// 设置弹层最大化
+layer.full(index);
+```
+
+设置弹层最小化
+
+`layer.min(index);`
+
+- 参数 `index` : 打开弹层时返回的唯一索引
+
+```
+// 打开弹窗
+var index = layer.open({
+ type: 1, // 页面层
+ content: '弹层内容'
+});
+// 设置弹层最大化
+layer.min(index);
+```
+
+还原弹层
+
+`layer.restore(index);`
+
+- 参数 `index` : 打开弹层时返回的唯一索引
+
+当弹层最大化或最小化状态时,执行该方法可还原弹层。
+
+
+## 贴士
+
+> layer 曾经可作为单独组件使用,鉴于维护成本的考量,目前 layer 组件已完全集成到 Layui 中,而单独版本已不做同步维护。 因此,建议直接使用 layui 中 layer 即可。
+
diff --git a/docs/layout/grid.md b/docs/layout/grid.md
new file mode 100644
index 000000000..cf60dc96d
--- /dev/null
+++ b/docs/layout/grid.md
@@ -0,0 +1,542 @@
+---
+title: 栅格布局
+toc: true
+---
+
+# 栅格布局
+
+> Layui 栅格系统是一套具备响应式能力的布局方案,采用业界比较常用的容器横向 `12` 等分规则,预设了 `5*12` 种 CSS 排列类,内置多种大小尺寸的多终端适配,能很好地实现响应式布局,这意味着一套系统,能同时适配于电脑的不同大小屏幕和手机、平板等移动屏幕,使得网页布局变得更加灵活,同时也极大地降低了 `HTML/CSS` 代码的耦合。
+
+示例
+
+> 贴士:以下示例中的*背景色*仅仅只是为了让布局效果显得更加直观,实际使用时并不需要背景色。
+
+
+
+- 始终等比例水平排列:
+
+
+
+
+
+
+
+
+- 移动设备、桌面端的组合响应式展现:
+
+
+
+
+
+
+
+- 移动设备、平板、桌面端的复杂组合响应式展现:
+
+
+
+
+
+
xs:6/12 | sm:6/12 | md:4/12
+
+
+
xs:6/12 | sm:6/12 | md:4/12
+
+
+
xs:4/12 | sm:12/12 | md:4/12
+
+
+
xs:4/12 | sm:7/12 | md:8/12
+
+
+
xs:4/12 | sm:5/12 | md:4/12
+
+
+
+
+
+- 常规布局:从小屏幕堆叠到桌面水平排列:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+- 列间隔:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+- 列偏移
+
+
+
+
+
+
+
+
+
+- 栅格嵌套:
+
+> 理论上,你可以对栅格进行无穷层次的嵌套,这更加增强了栅格的表现能力
+
+
+
+
+
+
+
+- 流体容器(宽度自适应,不固定):
+
+
+
+
+
+
+
+
+
+栅格布局规则
+
+
+
+
+
+
+
+
+ 1.
+ 采用 lay-row 来定义行,如:<div class="lay-row"></div>
+
+
+ 2.
+
+ 采用类似 lay-col-md* 这样的预设类来定义一组列(column),且放在行(row)内。其中:
+
+
+ 变量md 代表的是不同屏幕下的标记(可选值见下文)
+ 变量* 代表的是该列所占用的 12 等分数(如 6/12),可选值为 1 - 12
+ 如果多个列的“等分数值”总和等于 12,则刚好满行排列。如果大于12,多余的列将自动另起一行。
+
+
+
+
+
+ 3.
+ 列可以同时出现最多 5 种不同的组合,分别是:xs / sm / md / lg / xl 2.8+ ,以在不同尺寸屏幕下进行自动适配。
+
+
+ 4.
+ 可对列追加类似 lay-col-space5 、 lay-col-md-offset3 这样的预设类来定义列的间距和偏移。
+
+
+ 5.
+ 最后,在列(column)元素中放入你自己的任意元素填充内容,完成布局!
+
+
+
+
+响应式规则
+
+栅格的响应式能力,得益于 `CSS3` 媒体查询(`Media Queries`),针对不同尺寸的屏幕进行相应的适配处理。
+
+
+
+
+
+
+
+ 超小屏幕 (手机<768px)
+ 小屏幕 (平板≥768px)
+ 中等屏幕 (桌面≥992px)
+ 大型屏幕 (桌面≥1200px)
+ 超大屏幕 (桌面≥1400px)
+
+
+
+ lay-container
+ auto
+ 750px
+ 970px
+ 1170px
+ 1330px
+
+
+ 标记
+ xs
+ sm
+ md
+ lg
+ xl 2.8+
+
+
+ 列对应类
+ lay-col-xs*
+ lay-col-sm*
+ lay-col-md*
+ lay-col-lg*
+ lay-col-xl*
+
+
+ 总列数
+ 12
+
+
+ 响应行为
+ 始终按比例水平排列
+ 在当前屏幕下水平排列,如果屏幕大小低于临界值则堆叠排列
+
+
+
+
+响应式公共类
+
+
+
+
+
+
+
+
+ 类名(class)
+ 说明
+
+
+
+
+ lay-show-*-block
+ 定义不同设备下的 display: block; * 可选值有:xs、sm、md、lg、xl
+
+
+ lay-show-*-inline
+ 定义不同设备下的 display: inline; * 可选值同上
+
+
+ lay-show-*-inline-block
+ 定义不同设备下的 display: inline-block; * 可选值同上
+
+
+ lay-hide-*
+ 定义不同设备下的隐藏类,即: display: none; * 可选值同上
+
+
+
+
+布局容器
+
+将栅格放入一个带有 `class="lay-container"` 的特定容器中,以便在小屏幕以上的设备中固定宽度,让列可控。
+
+```
+
+```
+
+当然,你还可以不固定容器宽度。将栅格或其它元素放入一个带有 `class="lay-fluid"`的容器中,那么宽度将不会固定,而是 100% 适应
+
+```
+
+ ……
+
+```
+
+列间距
+
+
+
+
+
+
+
+
+ 通过“列间距”的预设类,来设定列之间的间距。且一行中最左的列不会出现左边距,最右的列不会出现右边距。列间距在保证排版美观的同时,还可以进一步保证分列的宽度精细程度。我们结合网页常用的边距,预设了 12 种不同尺寸的边距,分别是:
+
+
+
+
+lay-col-space1
+lay-col-space2
+lay-col-space4
+lay-col-space5
+lay-col-space6
+lay-col-space8
+lay-col-space10
+lay-col-space12
+lay-col-space14
+lay-col-space15
+lay-col-space16
+lay-col-space18
+lay-col-space20
+lay-col-space22
+lay-col-space24
+lay-col-space25
+lay-col-space26
+lay-col-space28
+lay-col-space30
+lay-col-space32
+
+即:支持列之间为 1px-32px 区间的所有双数间隔,以及 1px、5px、15px、25px 的单数间隔
+
+
+
+
+
+下面是一个简单的例子,列间距为 `16px`:
+
+```
+
+
+ 1/3
+
+
+ 1/3
+
+
+ 1/3
+
+
+```
+
+列偏移
+
+对列追加类似 `lay-col-md-offset*` 的预设类,从而让列向右偏移。如:`lay-col-md-offset3`,即代表在“中型桌面屏幕”下,让该列向右偏移 3 个列宽度。下面是一个采用「列偏移」机制让两个列左右对齐的实例
+
+```
+div class="lay-row">
+
+ 4/12
+
+
+ 偏移4列,从而在最右
+
+
+```
+
+> 请注意,列偏移可针对不同屏幕的标准进行设定,比如上述的例子,只会在桌面屏幕下有效,当低于桌面屏幕的规定的临界值,就会堆叠排列。
+
+IE8/9 兼容方案
+
+事实上 `IE8/IE9` 并不支持 `Media Queries`,但你可以使用下面的补丁进行兼容(补丁来自于开源社区):
+
+```
+
+
+```
+
+将上述代码放入你页面 `` 标签内的任意位置即可。
+
diff --git a/docs/layout/index.md b/docs/layout/index.md
new file mode 100644
index 000000000..54e08d617
--- /dev/null
+++ b/docs/layout/index.md
@@ -0,0 +1,149 @@
+---
+title: Admin UI 框体布局
+toc: true
+---
+
+# 框体布局
+
+> Layui 的主要应用场景是面向中后台的界面搭建,因此也提供了大框体布局方案。
+
+示例
+
+
+
+
+
+
+
+ layout 管理界面大布局示例 - Layui
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Layui 框体布局内容主体区域
+
+
+
+
+ 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 充数内容 你还真滑到了底部呀
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+> 小贴士:以上是一个基础的框体布局方案,若要实现诸如 `iframe` 跳转、侧边菜单收缩等功能,还需按照实际的业务需求自主实现。当然,也可以采用社区已有的 AdminUI 主题方案,如:layuiAdmin 等。
+
+Admin UI
+
+layuiAdmin 是一套用于开发通用型管理系统的纯静态的 `HTML` 网页界面主题,基于开源的 Layui Web 组件库制作而成,没有任何后端程序及数据库存储等服务端代码。开发者使用该网页模板,可省去前端的大量工作,从而更高效地开发 Web 应用系统。
+
diff --git a/docs/laypage/detail/demo.md b/docs/laypage/detail/demo.md
new file mode 100644
index 000000000..4be66bbf9
--- /dev/null
+++ b/docs/laypage/detail/demo.md
@@ -0,0 +1,279 @@
+
+
+
+
+
+
+
+
+
+
+自定义主题
+
+
+
+
+
+
+
+
+
+
+
+
+自定义文本
+
+
+
+
+
+
+
+
+
+
+不显示上一页、下一页
+
+
+
+
+
+
+
+
+
+
+只显示上一页、下一页、当前页
+
+
+
+
+
+
+
+
+
+
+自定义排版
+
+
+
+
+
+
+
+
+
+
+
+
+自定义每页条数的选择项
+
+
+
+
+
+
+
+
+
+
+完整显示
+
+
+
+
+
+
+
+
+
+
+高级 - 开启 HASH
+
+
+
+
+
+
+
+
+
+
+高级 - 将一段已知数组分页展示
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/laypage/detail/options.md b/docs/laypage/detail/options.md
new file mode 100644
index 000000000..22c7424e7
--- /dev/null
+++ b/docs/laypage/detail/options.md
@@ -0,0 +1,290 @@
+
+
+
+
+
+
+
+
+
+ 属性名
+ 描述
+ 类型
+ 默认值
+
+
+
+
+elem
+
+
+绑定分页容器。值可以是容器 `id` 或 DOM 对象。如:
+
+- `elem: 'id'` 注意:这里不能加 `#` 号
+- `elem: document.getElementById('id')`
+
+
+string DOM
+-
+
+
+count
+
+
+数据总数。一般通过后端得到
+
+
+number
+-
+
+
+limit
+
+
+每页显示的条数。
+
+
+number
+
+
+`10`
+
+
+
+
+limits
+
+
+每页条数的选择项。 若 `layout` 参数开启了 `limit` ,则会出现每页条数的 select 选择框
+
+
+array
+
+
+`[10,…,50]`
+
+
+
+
+curr
+
+
+初始化当前页码。
+
+
+number
+
+
+`1`
+
+
+
+
+groups
+
+
+连续出现的页码数量
+
+
+number
+
+
+`5`
+
+
+
+
+prev
+
+
+自定义“上一页”的内容,支持传入普通文本和 HTML
+
+
+string
+
+
+`上一页`
+
+
+
+
+next
+
+
+自定义“下一页”的内容,用法同上。
+
+
+string
+
+
+`下一页`
+
+
+
+
+first
+
+
+自定义“首页”的内容,用法同上。
+
+
+string
+
+
+`1`
+
+
+
+
+last
+
+
+自定义“尾页”的内容,用法同上。
+
+
+string
+
+
+*自动获得*
+
+
+
+
+layout
+
+
+自定义分页功能区域排版。可自由排列,可选值有:
+
+- `count` 数据总数区域
+- `prev` 上一页区域
+- `page` 分页区域
+- `next` 下一页区
+- `limit` 条目选项区域
+- `refresh` 页面刷新区
+- `skip` 快捷跳页区
+
+
+array
+
+
+查看默认值
+
+
+
+
+limitTemplet 2.8.18+
+
+
+用于自定义条目模板,如:
+
+```
+limitTemplet: function(item) {
+ return item + ' / page';
+}
+```
+
+
+function
+-
+
+
+skipText 2.8.18+
+
+
+用于自定义跳页区域文本,如:
+
+```
+skipText: ['Go to', '', 'Confirm']
+```
+
+
+array
+-
+
+
+countText 2.9.1+
+
+
+用于自定义总数区域文本,如:
+
+```
+countText: ['Total ','']
+```
+
+
+array
+-
+
+
+theme
+
+
+自定义主题。支持传入:颜色值或任意普通字符。如:
+
+- `theme: '#c00'` 直接设置当前页按钮背景色
+- `theme: 'xxx'` 会生成 `class="lay-laypage-xxx"` 的 CSS 类,以便自定义主题
+
+
+string
+-
+
+
+hash
+
+
+设置 `hash` 名称。设置该属性后,点击分页将会自动对当前 `url` 追加:`#{hash}={curr}`,从而在页面刷新时初始化当前页码。[#详细用法参考示例](#demo-hash)
+
+
+string
+-
+
+
+
+
+
+
+
+[回调函数](#options.callback)
+
+
+
+
+
+
+
+
+[jump](#options.jump)
+
+
+
+
+分页跳转后的回调函数。函数返回两个参数:
+
+- 参数 `obj` : 当前分页相关的所有选项值
+- 参数 `first` : 是否首次渲染,一般用于初始加载的判断
+
+```
+laypage.render({
+ elem: 'id',
+ count: 70, // 数据总数,从后端得到
+ jump: function(obj, first){
+ console.log(obj.curr); // 得到当前页,以便向服务端请求对应页的数据。
+ console.log(obj.limit); // 得到每页显示的条数
+
+ // 首次不执行
+ if(!first){
+ // do something
+ }
+ }
+});
+```
+
+
+
+
+
+
+
diff --git a/docs/laypage/index.md b/docs/laypage/index.md
new file mode 100644
index 000000000..52f8a4612
--- /dev/null
+++ b/docs/laypage/index.md
@@ -0,0 +1,37 @@
+---
+title: 分页组件 laypage
+toc: true
+---
+
+# 分页组件
+
+> 分页组件 `laypage` 提供了前端的分页逻辑,使得我们可以很灵活处理不同量级的数据,从而提升渲染效率。
+
+示例
+
+
+{{- d.include("/laypage/detail/demo.md") }}
+
+
+API
+
+| API | 描述 |
+| --- | --- |
+| var laypage = layui.laypage | 获得 `laypage` 模块。 |
+| [laypage.render(options)](#render) | laypage 组件渲染,核心方法。 |
+
+渲染
+
+`laypage.render(options);`
+
+- 参数 `options` : 基础属性选项。[#详见属性](#options)
+
+属性
+
+
+{{- d.include("/laypage/detail/options.md") }}
+
+
+## 小贴士
+
+laypage 组件只负责分页本身的逻辑,具体的数据请求及对应的视图渲染需要另外去完成。laypage 不仅能应用在一般的异步分页上,还可直接对一段已知数据进行分页展现,如 table 组件的分页就是采用的 laypage。
diff --git a/docs/laytpl/detail/demo.md b/docs/laytpl/detail/demo.md
new file mode 100644
index 000000000..e8380ca5e
--- /dev/null
+++ b/docs/laytpl/detail/demo.md
@@ -0,0 +1,187 @@
+
+
+{{!
+
+
+
+
模板
+ <textarea id="ID-tpl-src"></textarea>
+
+
+
数据
+ <textarea id="ID-tpl-data">
+{
+ "title": "Layui 常用组件",
+ "desc": "
一段带 HTML 的内容 ",
+ "list": [
+ {
+ "title": "弹层",
+ "name": "layer"
+ },
+ {
+ "title": "表单",
+ "name": "form"
+ },
+ {
+ "title": "表格",
+ "name": "table"
+ },
+ {
+ "title": "日期选择器",
+ "name": "laydate"
+ },
+ {
+ "title": "标签页",
+ "name": "tabs"
+ }
+ ]
+}
+ </textarea>
+
+
+
+
+
+
+
+
+
+!}}
+
+
diff --git a/docs/laytpl/detail/options.md b/docs/laytpl/detail/options.md
new file mode 100644
index 000000000..df90fd295
--- /dev/null
+++ b/docs/laytpl/detail/options.md
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+ 标签
+ 描述
+ 类型
+ 默认值
+
+
+ {{!
+
+open
+
+
+用于设置起始界定符
+
+
+string
+
+
+`{{`
+
+
+
+
+close
+
+
+用于设置结束界定符
+
+
+string
+
+
+`}}`
+
+
+
+
+cache 2.11+
+
+
+是否开启模板缓存,以便下次渲染时不重新编译模板
+
+
+boolean
+
+
+`true`
+
+
+
+
+condense 2.11+
+
+
+是否压缩模板空白符,如:将多个连续的空白符压缩为单个空格
+
+
+boolean
+
+
+`true`
+
+
+
+ !}}
+
+
diff --git a/docs/laytpl/detail/tags.md b/docs/laytpl/detail/tags.md
new file mode 100644
index 000000000..c971ad282
--- /dev/null
+++ b/docs/laytpl/detail/tags.md
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+ 标签
+ 描述
+
+
+ {{!
+
+{{= }}
+
+
+转义输出。若字段存在 HTML,将进行转义。
+
+
+
+
+{{- }}
+
+
+原文输出。即不对 HTML 字符进行转义,但需做好 XSS 防护。
+
+
+
+
+{{ }}
+
+
+Scriptlet 标签。一般用于流程控制,如:
+
+ ```js
+{{ if (d.title) { }}
+ 标题:{{= d.title }}
+{{ } else { }}
+ 默认标题
+{{ } }}
+ ```
+
+
+
+
+{{# }}
+
+
+注释标签。即仅在模板中显示,不在视图中输出。
+
+
+ !}}
+
+{{!{{! !}}!}}
+
+
+忽略标签。即该区域中的标签不会被解析,一般用于输出原始标签。如:
+
+```js
+{{! {{! 这里面的 {{= escape }} 等模板标签不会被解析 !}} !}}
+```
+
+
+
+
+
+
diff --git a/docs/laytpl/index.md b/docs/laytpl/index.md
new file mode 100644
index 000000000..284373815
--- /dev/null
+++ b/docs/laytpl/index.md
@@ -0,0 +1,271 @@
+---
+title: 模板引擎 laytpl
+toc: true
+---
+
+# 模板引擎
+
+> `laytpl` 是 Layui 内置的 JavaScript 模板引擎,采用原生控制流,在模板解析上有着比较出色的表现。
+
+在线测试
+
+对文本框中的*模板*或*数据*进行编辑,下方将呈现对应的*渲染结果*。
+
+
+{{- d.include("/laytpl/detail/demo.md") }}
+
+
+API
+
+| API | 描述 |
+| --- | --- |
+| var laytpl = layui.laytpl | 获得 `laytpl` 模块。 |
+| [var templateInst = laytpl(template, options)](#laytpl) | 创建模板实例。 |
+| [laytpl.config(options)](#config) | 设置基础选项默认值 |
+| [laytpl.extendVars(variables)](#variables) 2.11+ | 扩展模板内部变量 |
+
+创建模板实例
+
+`var templateInst = laytpl(template, options)`
+
+- 参数 `template` : 原始模板字符
+- 参数 `options` 2.8+ : 当前模板实例的选项。详见下述:[#基础选项](#options)
+
+该方法返回一个模板编译器实例,用于对模板进行数据渲染等操作,实例对象的成员有:
+
+| 实例成员 | 描述 |
+| --- | --- |
+| templateInst.render(data, callback) | 给模板实例进行数据渲染,返回渲染后的 HTML 字符 |
+| templateInst.compile(template) 2.11+ | 编译新的模板,会强制清除旧模板缓存 |
+| templateInst.config 2.11+ | 获取当前模板实例的配置选项 |
+
+通过将模板编译与渲染两个环节分开,我们可以在模板仅编译一次的情况下,对其渲染不同的数据,如:
+
+{{!
+```js
+var laytpl = layui.laytpl;
+
+// 创建模板实例
+var templateInst = laytpl('{{= d.name }}是一名{{= d.role }}');
+
+// 数据渲染 1
+templateInst.render({
+ name: '张三',
+ role: '全栈开发者'
+}, function(html) {
+ console.log(html); // 张三是一名全栈开发者
+});
+
+// 数据渲染 2
+var html = templateInst.render({
+ name: '王五',
+ role: '架构师'
+});
+```
+!}}
+
+若每次需要对不同的模板进行编译和数据渲染,你也可以使用链式写法,如:
+
+{{!
+```js
+laytpl('{{= d.name }}是一名{{= d.role }}').render({
+ name: '张三',
+ role: '全栈开发者'
+}, function(html) {
+ console.log(html); // 张三是一名全栈开发者
+});
+```
+!}}
+
+若模板字符较大,你可以将模板存放在页面某个标签中,如:
+
+{{!
+```js
+
+
+
+
+
+
+```
+!}}
+
+实际使用时,若模板通用,而数据不同,为了避免对模板进行不必要的重复编译,推荐将创建模板实例与数据渲染分开书写。
+
+基础选项
+
+创建模板实例时,你还可以对其设置一些选项,如:
+
+{{!
+```js
+// 创建模板实例
+var templateInst = laytpl(`
+ {{ let role = d.role || '全栈开发者'; }}
+ {{= d.name }}是一名{{= role }}
+`);
+var html = templateInst.render({ name: '张三' });
+```
+!}}
+
+支持设置的完整选项如下:
+
+
+{{- d.include("/laytpl/detail/options.md") }}
+
+
+
+
+
+{{- d.include("/laytpl/detail/tags.md") }}
+
+
+#### ⚡ 请注意:
+> *开发者在使用模板标签时,需确保模板中待输出的内容在开发者自身的可控范围内,尤其对于用户输入的字符要做好 XSS 防护,否则请避免使用该模板引擎,以免产生 XSS 安全隐患*。
+
+导入子模板 2.11+
+
+{{!
+laytpl 支持在模板中通过添加 `{{- include(id, data) }}` 语句引入子模板。`include` 语句参数解释:
+
+- `id` : 子模板 ID
+- `data` : 向子模版传入的数据
+
+为了引入的子模板不被转义,因此这里应该使用 `{{- }}`,即对子模板进行原文输出。示例:
+
+
+
+
+
+
+
+
+
+
+
+
+
+!}}
+
+若在 Node.js 环境,可通过 `laytpl.extendVars()` 方法重置 `include` 语句实现模板文件的导入。
+
+设置选项默认值
+
+`laytpl.config(options);`
+
+- 参数 `options`: 基础选项
+
+你可以设置任意选项的默认值,如:
+
+{{!
+```js
+laytpl.config({
+ open: '<%', // 自定义起始界定符
+ close: '%>', // 自定义起始界定符
+});
+
+// 创建模板实例
+var templateInst = laytpl(`
+ <% var roles = ["前端工程师","全栈工程师","架构师"]; %>
+ <%= d.name %>是一名<%= roles[d.role] %>
+`);
+// 渲染
+templateInst.render({
+ name: '张三',
+ role: 1
+}, function(string){
+ console.log(string); // 张三是一名全栈工程师
+});
+```
+!}}
+
+扩展模板内变量
+
+`laytpl.extendVars(variables)`
+
+- 参数 `variables` : 扩展的变量列表,变量值通常是一个函数
+
+事实上 laytpl 内置了一些模板内部方法,如 `_escape, include`。你可以对它们进行重构,或扩展更多内部变量,如:
+
+{{!
+```js
+// 扩展模板内部变量
+laytpl.extendVars({
+ // 重构 include 方法,实现引入模板文件
+ include: function(filename, data) {
+ // …
+ },
+ // 添加 toDataString 方法
+ toDataString: function(date) {
+ date = date || new Date();
+ return new Date(date).toLocaleDateString();
+ }
+});
+
+// 在模板中使用扩展的变量
+var templateInst = laytpl('日期:{{= toDataString(d.time) }}');
+templateInst.render({ time: 1742745600000 }, function(html) {
+ console.log(html);
+});
+```
+!}}
+
+## 💖 心语
+
+我们在 `2.11` 版本对 laytpl 完成了重要重构,使其能够具备应对更多复杂模板结构的解析能力。同时,为了与业界常用的 JavaScript 模板引擎 ejs 对齐,我们新增了与 ejs 相同的标签规则,这意味着同一套模板可以在 laytpl 和 ejs 中任意切换。
+
+作为 Layui 为数不多的一个纯功能型的模块,laytpl 承载了一些重要组件的功能支撑,如 table, dropdown 等,使得它们也能够自定义动态模板,增强了组件的可定制化。当然,laytpl 也可以作为前端单页面应用及 Express 等 Web 框架的视图引擎。
+
+
diff --git a/docs/menu/examples/demo.md b/docs/menu/examples/demo.md
new file mode 100644
index 000000000..e3ea9aaf4
--- /dev/null
+++ b/docs/menu/examples/demo.md
@@ -0,0 +1,118 @@
+
+
+
+
+ 基础菜单 - Layui
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/menu/index.md b/docs/menu/index.md
new file mode 100644
index 000000000..35e616b3c
--- /dev/null
+++ b/docs/menu/index.md
@@ -0,0 +1,64 @@
+---
+title: 基础菜单 menu
+toc: true
+---
+
+# 基础菜单
+
+> 基础菜单 `menu` 是垂直导航菜单的另一个替代方案,它是基于 `dropdown` 组件驱动的静态元素结构。
+
+示例
+
+
+
+{{- d.include("/menu/examples/demo.md") }}
+
+
+
+结构
+
+基础菜单层级与样式结构如下:
+
+- 通过 `` 命名基础菜单容器
+ - 追加 `className` 为 `lay-menu-lg` 可设置基础菜单的大尺寸风格
+ - 追加 `lay-accordion` 属性可设置手风琴效果 2.8.18+
+ - 通过 ` ` 放置菜单列表项
+ - 属性:
+ - 追加 `className` 为 `lay-menu-item-group` 可设置当前菜单为菜单组,即子菜单为纵向层级。
+ - 或追加 `className` 为 `lay-menu-item-parent` 可设置当前菜单为父级菜单,即子菜单为横向层级。
+ - 追加 `className` 为 `lay-menu-item-divider` 可设置分隔线。
+ - 追加 `className` 为 `lay-menu-item-up` 或 `lay-menu-item-down` 可设置子菜单默认收缩或展开。
+ - 追加 `className` 为 `lay-menu-item-checked` 可设置当前菜单为选中状态
+ - 添加 `lay-options="{}"` 可设置对应菜单列表的基础属性
+ - 内容:
+ - 通过 `
` 放置菜单标题容器
+ - 通过 `
` 放置横向子菜单外层面板
+ - 通过 `` 放置子菜单列表,其中 `` 中的规则同父级。
+- 再将基础菜单放置在一个面板容器中,以更好地定义尺寸、边框或阴影等外观,详细可参考上述示例。
+
+
+属性
+
+属性即命名在基础菜单列表元素 ` ` 中的 `lay-options` 属性值,如:` `,其支持的属性如下:
+
+| 属性 | 描述 |
+| --- | --- |
+| title | 设置菜单标题。默认读取标题容器内容中的文本。 |
+| type | 设置菜单类型。可选值如下:若不设定,则表示为常规菜单项 `type:'group'` 菜单组,子菜单为纵向层级 `type:'parent'` 父级菜单,子菜单为横向层级 |
+| isAllowSpread | 子菜单是否允许展开收缩操作。默认 `true` |
+
+事件
+
+`dropdown.on('click(filter)', callback)`
+
+- 参数 `click(filter)` 是一个特定结构。
+ - `click` 为基础菜单项点击事件固定值;
+ - `filter` 为基础菜单容器属性 `lay-filter` 对应的值。
+- 参数 `callback` 为事件执行时的回调函数,并返回一个 object 类型的参数。
+
+点击菜单列表项时触发。用法:[#详见示例](#examples)
+
+## 贴士
+
+基础菜单相当于是 `dropdown` 组件的一种静态化呈现,因此在事件等动态操作上需借助 `dropdown` 组件的 API 来完成。
+
diff --git a/docs/modules.md b/docs/modules.md
new file mode 100644
index 000000000..8864c8326
--- /dev/null
+++ b/docs/modules.md
@@ -0,0 +1,297 @@
+---
+title: 模块系统
+toc: true
+---
+
+模块系统
+
+> Layui 制定了一套适合自身应用场景的轻量级模块规范,以便在不同规模的项目中,也能对前端代码进行很好的管理或维护。 Layui 的轻量级模块系统,并非有意违背 CommonJS 和 ES Module ,而是试图以更简单的方式去诠释高效,这种对*返璞归真*的执念源于在主流标准尚未完全普及的前 ES5 时代,后来也成为 Layui 独特的表达方式,而沿用至今。
+
+如下是一个关于模块的简单示例:
+
+```
+// 定义模块(通常单独作为一个 JS 文件)
+layui.define([mods], function(exports){
+ // …
+
+ exports('mod1', api); // 输出模块
+});
+
+// 使用模块
+layui.use(['mod1'], function(args){
+ var mod1 = layui.mod1;
+
+ // …
+});
+```
+
+我们可以将其视为「像使用普通 API 一样来管理模块」,在此前提下,组件的承载也变得轻松自如,我们完全可以游刃在以浏览器为宿主的原生态的 HTML/CSS/JavaScript 的开发模式中,而不必卷入层出不穷的主流框架的浪潮之中,给心灵一个栖息之所。
+
+当然,Layui 自然也不是一个模块加载器,而是一套相对完整的 UI 解决方案,但与 Bootstrap 又并不相同,除了 HTML+CSS 本身的静态化处理,Layui 的组件更倾向于 JavaScript 的动态化渲染,并为之提供了相对丰富和统一的 API,使用时,只需稍加熟悉,便可在各种交互中应付自如。
+
+
+定义模块
+
+`layui.define([mods], callback);`
+
+- 参数 `mods` 可选,用于声明该模块所依赖的模块;
+- 参数 `callback` 即为模块加载完毕的回调函数,它返回一个 `exports` 参数,用于输出该模块的接口。
+
+```
+/** demo.js **/
+layui.define(function(exports){
+ // do something
+
+ // 输出 demo 模块
+ exports('demo', {
+ msg: 'Hello Demo'
+ });
+});
+
+// 若该模块需要依赖别的模块,则在 `mods` 参数中声明即可:
+// layui.define(['layer', 'form'], callback);
+```
+
+如上所示,`callback` 返回的 `exports` 参数是一个函数,它接受两个参数:参数一为*模块名*,参数二为*模块接口*。
+
+另外, `callback` 将会在初次加载该模块时被自动执行。而有时,在某些特殊场景中可能需要再次执行该 `callback`,那么可以通过 `layui.factory(mod)` 方法获得。如:
+
+```
+var demoCallback = layui.factory('demo'); // 得到定义 demo 模块时的 `callback`
+```
+
+- **模块命名空间**
+
+Layui 定义的模块将会被绑定在 `layui` 对象下,如:`var demo = layui.demo;` 每个模块都有一个特定命名,且无法被占用,所以你无需担心模块的命名空间被污染,除非通过 `layui.disuse([mods])` 方法弃用已定义的模块。
+
+以下是定义一个「依赖 Layui 内置模块」的模块示例:
+
+```
+layui.define(['layer', 'laydate'], function(exports){
+ var layer = layui.layer // 获得 layer 模块
+ var laydate = layui.laydate; // 获得 laydate 模块
+
+ // 输出模块
+ exports('demo', {}); // 模块名 demo 未被占用,此时模块定义成功
+ // exports('layer', {}); // 模块名 layer 已经存在,此时模块定义失败
+});
+```
+
+同样的,在「扩展模块」时,也同样不能命名已经存在的模块名。
+
+
+使用模块
+
+`layui.use([mods], callback);`
+
+- 参数 `mods` 若填写,必须是已被成功定义的模块名;
+ 注2.6+ :若 mods 不填,即只传一个 callback 参数时,则表示引用所有内置模块。
+- 参数 `callback` 即为使用模块成功后回调函数。
+ 注2.6+ :该回调会在 html 文档加载完毕后再执行,确保你的代码在任何地方都能对元素进行操作。
+
+```
+// 使用指定模块
+layui.use(['layer', 'table'], function(){
+ var layer = layui.layer;
+ var table = layui.table;
+
+ // do something
+});
+
+// 使用所有内置模块(layui v2.6 开始支持)
+layui.use(function(){
+ var layer = layui.layer;
+ var table = layui.table;
+ var laydate = layui.laydate;
+ // …
+
+ // do something
+});
+```
+
+你还可以通过 `callback` 返回的参数得到模块对象,如:
+
+```
+layui.use(['layer', 'table'], function(layer, table){
+ // 使用 layer
+ layer.msg('test');
+
+ // 使用 table
+ table.render({});
+});
+```
+
+- **执行「定义模块」时的回调函数**
+
+在上文的定义模块中,我们提到一个特殊场景,即重新获取定义模块时的 `callback` 函数, 譬如在*单页面应用*开发中,我们在视图碎片中使用某个模块,由于定义模块时的 `callback` 只会在模块初次加载中被调用,而当视图碎片在每次被渲染时,又往往需要该 `callback` 被再次执行,那么则可以通过以下方式实现:
+
+```
+// 在单页面视图碎片渲染时,再次调用「定义模块」时的 `callback`
+layui.use('demo', layui.factory('demo'));
+```
+
+扩展模块
+
+`layui.extend(settings);`
+
+- 参数 `settings` : 扩展模块的相关配置,如模块名、模块路径等。
+
+除了 Layui 的内置模块,在实际项目开发时,必不可少也需要扩展模块。我们在前文的「模块命名空间」提到,模块名具有唯一性,即不可被占用,因此我们扩展的模块必须是一个未被定义过的模块名。
+
+现在,让我们尝试扩展一个 Layui 第三方模块。
+
+### 扩展遵循 Layui 规范的模块
+
+1. **创建模块和定义模块**
+
+假设创建一个模块名为 `testModule` 的模块,新建 `testModule.js` 文件并放入项目的任意目录中(但应避免放入到 Layui 原始目录)。接着我们开始定义 `testModule` 模块,并编写该模块主体代码。
+
+```js
+/**
+ * 定义 testModule 模块
+ **/
+layui.define(function(exports){ // 也可以依赖其他模块
+ var obj = {
+ hello: function(str){
+ alert('Hello '+ (str || 'TestModule'));
+ }
+ };
+
+ // 输出 testModule 接口
+ exports('testModule', obj);
+});
+```
+
+2. **声明模块和使用模块**
+
+现在,我们只需声明模块名及模块文件路径,即完成模块扩展。
+
+```js
+// 假设 testModule 模块文件所在路径在:/js/layui_exts/testModule.js
+layui.config({
+ base: '/js/layui_exts/' // 设置用于扩展模块的基础路径
+}).extend({
+ testModule: 'testModule', // 定义模块名和模块路径,会前置追加 base 基础路径
+ // test1: 'test1' // 还可同时声明其他更多模块
+});
+
+// 也可以不前置追加 base 基础路径,即设置单独路径
+layui.extend({
+ testModule: '{/}/js/layui_exts/testModule' // 开头特定符 {/} 即代表采用单独路径
+});
+
+// 然后我们就可以像使用内置模块一样使用扩展模块
+layui.use(['testModule', 'test1'], function(){
+ var testModule = layui.testModule;
+ // var test1 = layui.test1;
+
+ testModule.hello('World');
+});
+```
+
+扩展任意外部模块 2.11+
+
+我们在 `2.11.0` 版本新增了无缝扩展任意外部模块的支持,即无需遵循 Layui 模块规范的第三方库也能通过 Layui 去加载,并且无需对外部模块做任何的代码改动,只需在 `layui.extend()` 方法中声明模块名、路径和接口即可。
+
+当声明的模块接受的是一个 `object` 类型时,即意味着声明任意外部模块。声明外部模块的对象由以下选项组成:
+
+- `src` : 模块路径,可以是项目的相对路径,也可以是任意外部模块的公共 CDN 地址;
+- `api` : 接口名称,通常是模块提供的全局对象
+
+下面是一个扩展任意外部模块的示例:
+
+```js
+// 扩展任意外部模块
+layui.extend({
+ marked: {
+ src: 'https://cdnjs.cloudflare.com/ajax/libs/marked/15.0.7/marked.min.js', // 模块路径
+ api: 'marked' // 接口名称
+ },
+ Prism: {
+ src: 'https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/prism.min.js',
+ api: 'Prism'
+ }
+});
+
+// 加载扩展模块
+layui.use(['marked', 'Prism'], function() {
+ console.log('任意外部模块 loaded: ')
+ console.log(' > marked: ', layui.marked);
+ console.log(' > Prism: ', layui.Prism);
+});
+```
+
+> 扩展模块是项目开发的重要环节,它既可以是工具性组件,也可以是纯业务组件,是 Layui 的延伸,也是项目的支撑。
+
+
+建立模块入口
+
+在不同的页面中,可能需要用到不同的业务模块。以首页为例:
+
+```
+
+
+```
+
+上述的 `index` 模块即对应的模块文件 `/js/modules/index.js`,它同样也必须符合 Layui 模块规范。如:
+
+```
+/**
+ * index.js 首页业务模块
+ */
+layui.define(['layer', 'form'], function(exports){
+ var layer = layui.layer;
+ var form = layui.form;
+
+ layer.msg('Hello Index');
+
+ exports('index', {}); // 输出模块名需和 use 和 extend 时的模块名一致
+});
+```
+
+**合并模块入口**
+
+当项目存在许多不同的业务模块(且存在一定的依赖关系),我们又希望在页面中建立统一的入口模块。如:
+
+```
+// mod1.js
+layui.define('layer', function(exports){
+ // …
+ exports('mod1', {});
+});
+
+// mod2.js,假设依赖 mod1 和 form
+layui.define(['mod1', 'form'], function(exports){
+ // …
+ exports('mod2', {});
+});
+
+// mod3.js
+// …
+
+// index.js 主入口模块
+layui.define('mod2', function(exports){
+ // …
+ exports('main', {});
+});
+```
+
+我们可以将上述模块合并为一个文件来加载,即借助构建工具(如 Gulp)将上述的 mod1、mod2、mod3、index 等业务模块合并到一个模块文件:`index.js`,此时只需在页面统一加载该模块即可。这样我们最多只需要加载两个 JS 文件:`layui.js、index.js`,这将大幅度减少静态资源的请求。
+
+
+
+
+
+## 小贴士
+
+> 综上: Layui 轻量级模块系统,无非就是:定义模块、使用模块、弃用模块、扩展模块的相互呼应,翻译成 API 即:
+> - `layui.define();`
+> - `layui.use();`
+> - `layui.disuse();`
+> - `layui.extend();`
+> ---
+> 熟练运用,可让您的项目更利于维护。
diff --git a/docs/nav/examples/side.md b/docs/nav/examples/side.md
new file mode 100644
index 000000000..4b0c6affd
--- /dev/null
+++ b/docs/nav/examples/side.md
@@ -0,0 +1,43 @@
+
+
+
+
+ 侧边垂直导航 - Layui
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/nav/index.md b/docs/nav/index.md
new file mode 100644
index 000000000..1e93ee320
--- /dev/null
+++ b/docs/nav/index.md
@@ -0,0 +1,348 @@
+---
+title: 导航菜单 nav
+toc: true
+---
+
+# 导航菜单
+
+> 导航菜单包含水平导航和垂直导航, 在 `2.x` 版本中,`nav` 组件属于 `element` 模块的子集。
+
+水平导航
+
+一般用于页面头部菜单。样式规则如下:
+
+- 通过 `class="lay-nav"` 设置导航容器
+- 通过 `class="lay-nav-item"` 设置导航菜单项
+ - 追加 `className` 为 `lay-this` 可设置菜单选中项
+- 通过 `class="lay-nav-child"` 设置导航子菜单项
+ - 追加 `className` 为 `lay-nav-child-c` 和 `lay-nav-child-r` 可设置子菜单居中和向右对齐
+
+
+常规用法
+
+
+
+
+
+
+
+
+
+备注:滑块效果仅跟随不存在子菜单的菜单项。
+
+加入徽章等元素
+
+
+
+
+
+
+
+
+
+导航主题
+
+给导航容器追加任意背景色 `class`,内置背景色参考:[#背景色公共类](../class/#bg)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+垂直导航
+
+一般用于左侧侧边菜单。样式规则如下:
+
+- 在水平导航的 `class` 规则上,通过设置 `class="lay-nav lay-nav-tree"` 定义垂直导航容器。
+- 通过 `class="lay-nav-itemed"` 设置父菜单项为展开状态
+- 通过给导航容器追加 `class="lay-nav-side"` 可设置侧边垂直导航
+- 其余结构及填充内容与水平导航完全相同
+
+
+
+
+
+
+
+
+
+侧边垂直导航
+
+
+
+{{- d.include("/nav/examples/side.md") }}
+
+
+
+API
+
+| API | 描述 |
+| --- | --- |
+| var element = layui.element | 获得 `element` 模块。 |
+| [element.render(\'nav\', \'filter\')](#render) | 导航菜单 `nav` 组件渲染。 |
+
+渲染
+
+`element.render('nav', filter);`
+
+- 参数 `'nav'` 是渲染导航的固定值
+- 参数 `filter` : 对应导航容器 `lay-filter` 的属性值或2.9.15+ 指定元素的 jQuery 对象
+
+`nav` 组件会在元素加载完毕后,自动对导航完成一次渲染,因此该方法主要用于对动态插入的导航元素的初始化渲染。
+
+```
+
+
+
+
+```
+
+属性
+
+| 属性 | 描述 |
+| --- | --- |
+| lay-accordion 2.8.18+ | 导航容器属性。用于开启垂直导航菜单展开时的手风琴效果。如: `…
` |
+| lay-bar | 导航容器属性。用于禁用滑块跟随功能。如: `…
` |
+| lay-unselect | 导航菜单项属性。 设置后,点击对应菜单项时,不会出现选中效果。 |
+
+
+事件
+
+`element.on('nav(filter)', callback)`
+
+- 参数 `nav(filter)` 是一个特定结构。
+ - `nav` 为导航事件固定值;
+ - `filter` 为导航容器属性 `lay-filter` 对应的值。
+- 参数 `callback` 为事件执行时的回调函数,并返回一个 `object` 类型的参数。
+
+当点击导航父级菜单和二级菜单时触发。示例:
+
+
+
+
+
+
+
+
+
+
+面包屑导航
+
+面包屑导航主要用于指示当前页面所处的位置,并能返回到上级页面。
+
+
+
+默认面包屑
+
+
+ 首页
+ 演示
+ 导航元素
+
+
+自定义分隔符
+
+
+ 首页
+ 国际新闻
+ 亚太地区
+ 正文
+
+
+门户频道
+
+
+ 娱乐
+ 八卦
+ 体育
+ 搞笑
+ 视频
+ 游戏
+ 综艺
+
+
+
+
+
+
+### **面包屑导航渲染**
+
+`element.render('breadcrumb', filter);`
+
+- 参数 `'breadcrumb'` 是渲染面包屑导航的固定值
+- 参数 `filter` : 对应面包屑导航容器 `lay-filter` 的属性值或2.9.15+ 指定元素的 jQuery 对象
+
+该方法主要用于对动态插入的面包屑导航的初始化渲染,用法同上述导航菜单。
+
diff --git a/docs/panel/index.md b/docs/panel/index.md
new file mode 100644
index 000000000..d00466bad
--- /dev/null
+++ b/docs/panel/index.md
@@ -0,0 +1,289 @@
+---
+title: 面板 panel,card,collapse
+toc: true
+---
+
+# 面板
+
+> 面板是一个包含普通面板(panel)、卡片面板(card)、折叠面板(collapse)的集合
+
+常规面板
+
+常规面板通常作为包裹其他元素的形式存在,如与基础菜单 `menu` 经常搭配使用。
+
+
+
+
+
+
+
+卡片面板
+
+
+
+
+
+
+
+
+
+ 卡片式面板面板通常用于非白色背景色的主体内
+ 从而映衬出边框投影
+
+
+
+
+
+
+
+ 结合 layui 的栅格系统
+ 轻松实现响应式布局
+
+
+
+
+
+
+
+
+折叠面板
+
+
+
+
+
+
Collapse Title 1
+
+
Content 1 (添加 lay-show 类设置初始展开)
+
+
+
+
+
Collapse Title 3
+
+
+ Content list
+ Content list
+
+
+
+
+
+
+
+
+
+
+
+开启手风琴
+
+在折叠面板容器上追加 `lay-accordion` 属性,开启手风琴效果,即点击展开当前面板的同时,折叠其他面板。
+
+
+
+
+
+
layui 主要面向哪些用户群体?
+
+ Layui 作为一个前端界面组件库,但面向的却主要是后端开发者。
+ 即无需涉足各类构建工具,只需面向浏览器本身,便可将页面所需呈现的元素与交互信手拈来。
+
+
+
+
+
Why are my eyes always brimming with tears?
+
+
Because I love this land so deeply…
+
+
+
+
+
+
+
+
+
+折叠面板嵌套
+
+折叠面板内部支持无限嵌套,即折叠面板中再放置无限层级的折叠面板,以实现树形折叠结构。如:
+
+
+
+
+
+
文学家
+
+
+
+
+
唐代
+
+
+
+
+
杜甫
+
+ 唐代著名诗人,与李白齐名
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+折叠面板渲染
+
+
+`element.render('collapse', filter);`
+
+- 参数 `'collapse'` : 渲染折叠面板的固定值
+- 参数 `filter` : 对应折叠面板容器 `lay-filter` 的属性值或2.9.15+ 指定元素的 jQuery 对象
+
+在元素加载完毕后,`element` 模块会自动对元素进行一次渲染。而当元素为动态插入时,需通过该方法完成初始化渲染。
+
+
+折叠面板事件
+
+`element.on('collapse(filter)', callback)`
+
+- 参数 `collapse(filter)` 是一个特定结构。
+ - `collapse` 为折叠面板点击事件固定值;
+ - `filter` 为导航容器属性 `lay-filter` 对应的值。
+- 参数 `callback` 为事件执行时的回调函数,并返回一个 `object` 类型的参数。
+
+
+
+
+
+
+
+
Collapse Title 3
+
+
+ Content list
+ Content list
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/progress/index.md b/docs/progress/index.md
new file mode 100644
index 000000000..de2718ade
--- /dev/null
+++ b/docs/progress/index.md
@@ -0,0 +1,236 @@
+---
+title: 进度条 progress
+toc: true
+---
+
+# 进度条
+
+> 进度条 `progress` 可应用于许多业务场景,如任务完成进度、loading 等等。
+
+示例
+
+
+
+
+
+
+
+
+
+
+
+
+
+进度条宽度是 100% 适配于它的父级元素,如上面的进度条是在一个 300px 的父容器中。
+
+
+进度条主题
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+大号进度条
+
+通过对进度条容器追加 `className` 为 `lay-progress-big` 可设置大尺寸风格的进度条。
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+显示进度值
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+API
+
+| API | 描述 |
+| --- | --- |
+| var element = layui.element | 获得 `element` 模块。 |
+| [element.render(\'progress\', filter)](#render) | 进度条 `progress` 组件渲染。 |
+| [element.progress(filter, percent)](#progress) | 设置进度值 |
+
+渲染
+
+`element.render('progress', filter);`
+
+- 参数 `'progress'` : 渲染进度条的固定值
+- 参数 `filter` : 对应进度条容器 `lay-filter` 的属性值或2.9.15+ 指定元素的 jQuery 对象
+
+在元素加载完毕后,element 模块会自动对元素进行一次渲染。而当元素为动态插入时,需通过该方法完成初始化渲染。
+
+```
+
+
+
+
+```
+
+
+属性
+
+| 属性 | 描述 |
+| --- | --- |
+| lay-percent | 用于设置进度条的值,进度条内层容器属性。支持 *百分比* 和 *分数* 形式。用法详见:[#示例](#examples) |
+| lay-showpercent | 是否显示进度值,进度条外层容器属性,默认不显示。用法详见:[#示例](#showpercent) |
+
+
+设置进度值
+
+`element.progress(filter, percent);`
+
+- 参数 `filter` : 对应进度条容器 `lay-filter` 的属性值
+- 参数 `'percent'` : 进度条的值
+
+该方法用于动态改变进度条的值。示例:
+
+
+
+
+
+
+
+
+ 设置 50%
+ 模拟 loading
+
+
+
+
+
+
+
+
diff --git a/docs/rate/detail/demo.md b/docs/rate/detail/demo.md
new file mode 100644
index 000000000..2e01e28e6
--- /dev/null
+++ b/docs/rate/detail/demo.md
@@ -0,0 +1,187 @@
+
+
+
+
+
+
+
+
+
+显示文字
+
+
+
+
+
+
+
+
+
+
+半星效果
+
+
+
+
+
+
+
+
+
+
+
+
+自定义文本
+
+
+
+
+
+
+
+
+
+
+
+
+自定义长度
+
+
+
+
+
+
+
+
+
+
+
+
+只读
+
+
+
+
+
+
+
+
+
+
+自定义主题色
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/rate/detail/options.md b/docs/rate/detail/options.md
new file mode 100644
index 000000000..168f98166
--- /dev/null
+++ b/docs/rate/detail/options.md
@@ -0,0 +1,141 @@
+
+
+
+
+
+
+
+
+
+ 属性名
+ 描述
+ 类型
+ 默认值
+
+
+
+
+elem
+
+
+绑定元素选择器或 DOM 对象
+
+
+string/DOM
+-
+
+
+length
+
+
+评分的最大长度值,即星星的数量。
+
+
+number
+
+
+`5`
+
+
+
+
+value
+
+
+评分的初始值
+
+
+number
+
+
+`0`
+
+
+
+
+half
+
+
+是否可以选择半星。若开启,则 `value` 支持小数点,如:
+
+```
+value: '3.5'
+```
+
+
+boolean
+
+
+`false`
+
+
+
+
+theme
+
+
+主题色
+
+
+string
+
+
+`#FFB800`
+
+
+
+
+text
+
+
+是否显示评分对应的文本
+
+
+boolean
+
+
+`false`
+
+
+
+
+readonly
+
+
+是否只读,即只用于展示,而不可点击
+
+
+boolean
+
+
+`false`
+
+
+
+
+setText
+
+
+初始设置自定义文本的回调函数。 并返回当前 `value` 参数。用法详见:[#自定义文本](#demo-setText)
+
+
+
+
+choose
+
+
+选择评分后的回调函数。并返回当前 `value` 参数
+
+```
+rate.render({
+ elem: '#id',
+ choose: function(value){
+ console.log(value); // 获得选中的评分值
+ }
+});
+```
+
+
+
+
+
diff --git a/docs/rate/index.md b/docs/rate/index.md
new file mode 100644
index 000000000..81cf7e1df
--- /dev/null
+++ b/docs/rate/index.md
@@ -0,0 +1,58 @@
+---
+title: 评分组件 rate
+toc: true
+---
+
+# 评分组件
+
+> 评分组件 `rate` 一般用于等级展示或评价类操作。
+
+示例
+
+
+{{- d.include("/rate/detail/demo.md") }}
+
+
+
+
+API
+
+| API | 描述 |
+| --- | --- |
+| var rate = layui.rate | 获得 `rate` 模块。 |
+| [基础接口](../component/#export) 2.11+ | 该组件由 `component` 构建,因此继承其提供的基础接口。|
+| [rate.render(options)](#render) | rate 组件渲染,核心方法。 |
+
+渲染
+
+`rate.render(options);`
+
+- 参数 `options` : 基础属性选项。[#详见属性](#options)
+ 注 2.8+ : 除 `elem` 属性外,其他基础属性也可以直接写在元素的 `lay-options="{}"` 属性中。
+
+```
+
+
+
+
+
+
+```
+
+属性
+
+
+{{- d.include("/rate/detail/options.md") }}
+
diff --git a/docs/slider/detail/demo.md b/docs/slider/detail/demo.md
new file mode 100644
index 000000000..89d3399cd
--- /dev/null
+++ b/docs/slider/detail/demo.md
@@ -0,0 +1,288 @@
+
+
+
+
+
+
+
+
+
+定义初始值
+
+
+
+
+
+
+
+
+
+
+设置最大和最小值
+
+
+
+
+
+
+
+
+
+
+设置步长
+
+
+
+
+
+
+
+
+
+
+
+
+设置提示文本
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+开启范围选择
+
+
+
+
+
+
+
+
+
+
+
+
+垂直滑块
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+自定义主题色
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+禁用滑块
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/slider/detail/options.md b/docs/slider/detail/options.md
new file mode 100644
index 000000000..e033a80f6
--- /dev/null
+++ b/docs/slider/detail/options.md
@@ -0,0 +1,268 @@
+
+
+
+
+
+
+
+
+
+ 属性名
+ 描述
+ 类型
+ 默认值
+
+
+
+
+elem
+
+
+绑定元素选择器或 DOM 对象
+
+
+string/DOM
+-
+
+type
+
+
+滑块类型,可选值有:
+
+- `default` 水平滑块(默认)
+- `vertical`垂直滑块
+
+
+string
+
+
+`default`
+
+
+
+
+value
+
+
+滑块初始值。
+
+- 默认可直接设置数值,如: `value: 50`
+- 若滑块开启 `range: true` 区间选择,则值为数组,亦表示开始和结尾的区间,如: `value: [30, 60]`
+
+
+number array
+-
+
+
+range
+
+
+是否开启滑块的区间选择。若开启,则滑块将出现两个可拖拽的点。
+
+
+boolean
+
+
+`false`
+
+
+
+
+min
+
+
+滑块的最小值
+
+
+number
+
+
+`0`
+
+
+
+
+max
+
+
+滑块的最大值
+
+
+number
+
+
+`100`
+
+
+
+
+step
+
+
+滑块单次拖动的步长
+
+
+number
+
+
+`1`
+
+
+
+
+showstep
+
+
+是否显示间断点
+
+
+boolean
+
+
+`false`
+
+
+
+
+tips
+
+
+鼠标移入当前圆点,是否显示当前值
+
+
+boolean
+
+
+`true`
+
+
+
+
+tipsAlways 2.9.3+
+
+
+是否始终显示提示文本,要开启此功能,tips 必须设置为 `true` 才能生效
+
+
+boolean
+
+
+`false`
+
+
+
+
+input
+
+
+是否显示滑块的数字输入框。 注:若设置 `range: true` 则该属性强制无效。
+
+
+boolean
+
+
+`false`
+
+
+
+
+height
+
+
+滑动条高度。 必须设置 `type: 'vertical'` 属性,即垂直滑块时有效。
+
+
+number
+
+
+`200`
+
+
+
+
+theme
+
+
+滑块的主题色。
+
+
+string
+-
+
+
+disabled
+
+
+是否禁用滑块
+
+
+boolean
+
+
+`false`
+
+
+
+
+setTips
+
+
+滑块拖拽时设置提示文本的回调函数。并返回当前的 `value` 参数。用法详见:[#设置提示文本](#demo-setTips)
+
+
+
+
+
+
+
+
+
+[回调函数](#options.callback)
+
+
+
+
+
+
+change
+
+
+滑块数值发生改变的回调函数。并返回当前的 `value` 参数。
+
+```
+slider.render({
+ elem: '#id',
+ change: function(value){
+ console.log(value) // 滑块当前值
+ // do something
+ }
+});
+```
+
+一般可在该回调中将 `value` 同步给表单隐藏域,或者进行一些其它操作。
+
+
+
+
+done 2.8+
+
+
+滑块拖拽完毕的回调函数。并返回当前的 `value` 参数。滑块拖动过程中不会触发。
+
+```
+slider.render({
+ elem: '#id',
+ done: function(value){
+ console.log(value) // 滑块当前值
+ // do something
+ }
+});
+```
+
+若需将 `value` 异步发送给后端,一般采用 `done` 回调,而非 `change` 回调。
+
+
+
+
+
+
diff --git a/docs/slider/index.md b/docs/slider/index.md
new file mode 100644
index 000000000..1bad6ff50
--- /dev/null
+++ b/docs/slider/index.md
@@ -0,0 +1,95 @@
+---
+title: 滑块组件 slider
+toc: true
+---
+
+# 滑块组件
+
+> 滑块组件 `slider` 是一个拖拽选值的交互性组件,常与 `form` 元素结合使用。
+
+示例
+
+
+
+{{- d.include("/slider/detail/demo.md") }}
+
+
+API
+
+| API | 描述 |
+| --- | --- |
+| var slider = layui.slider | 获得 `slider` 模块。 |
+| [基础接口](../component/#export) 2.12+ | 该组件由 `component` 构建,因此继承其提供的基础接口。|
+| [var inst = slider.render(options)](#render) | slider 组件渲染,核心方法。 |
+| [inst.setValue(value)](#setValue) | 设置滑块值 |
+| inst.config | 获得当前实例的属性选项 |
+
+渲染
+
+`slider.render(options);`
+
+- 参数 `options` : 基础属性选项。[#详见属性](#options)
+ 注 2.8+ : 除 `elem` 属性外,其他基础属性也可以直接写在元素的 `lay-options="{}"` 属性中。
+
+```
+
+
+
+
+
+
+```
+
+
+该方法返回一个实例对象,包含操作当前实例的相关方法成员。
+
+```
+var inst = slider.render(options);
+console.log(inst); // 得到当前实例对象
+```
+
+设置滑块值
+
+`inst.setValue(value, index)`
+
+- 参数 `value` : 要设置的滑块数值
+- 参数 `index` : 滑块所在的区间开始值或结尾值的索引,开始值:`0` ; 结尾值:`1`
+
+```
+var slider = layui.slider;
+
+// 渲染
+var inst = slider.render({
+ elem: '#id'
+ // …
+});
+
+// 设置滑块值
+inst.setValue(20);
+
+// 若滑块开启了范围,即: `range: true`
+ins1.setValue(20, 0) // 设置开始值
+ins1.setValue(60, 1) // 设置结尾值
+```
+
+属性
+
+
+{{- d.include("/slider/detail/options.md") }}
+
+
diff --git a/docs/table/detail/demo.md b/docs/table/detail/demo.md
new file mode 100644
index 000000000..b489e38e1
--- /dev/null
+++ b/docs/table/detail/demo.md
@@ -0,0 +1,189 @@
+综合演示 🔥
+
+
+
+{{- d.include("/table/examples/demo.md") }}
+
+
+
+静态表格
+
+静态表格是指内容已经存在于页面中的 `` 元素,且可通过一些*特定属性*设定不同风格。
+
+
+
+{{- d.include("/table/examples/static.md") }}
+
+
+
+模板配置渲染
+
+在上文「[综合演示](#examples)」中,是通过组件核心方法完成的渲染。除此,还可以在模板上直接配置相关属性,让其自动完成渲染。
+
+
+
+{{- d.include("/table/examples/autoRender.md") }}
+
+
+
+静态表格转换
+
+
+
+{{- d.include("/table/examples/init.md") }}
+
+
+
+已知数据渲染
+
+
+
+{{- d.include("/table/examples/data.md") }}
+
+
+
+自定义模板
+
+
+
+{{- d.include("/table/examples/templet.md") }}
+
+
+
+自定义样式 2.7+
+
+
+
+{{- d.include("/table/examples/css.md") }}
+
+
+
+自定义分页
+
+
+
+{{- d.include("/table/examples/page.md") }}
+
+
+
+外部搜索
+
+
+
+{{- d.include("/table/examples/search.md") }}
+
+
+
+编辑的权限控制 2.7+
+
+以下演示一个根据返回数据中某个字段来判断是否开启该行的编辑,*单击对应行*可进入单元格编辑。
+
+
+
+{{- d.include("/table/examples/editable.md") }}
+
+
+
+实现多样化编辑
+
+
+
+{{- d.include("/table/examples/editModes.md") }}
+
+
+
+转换数据格式
+
+
+
+{{- d.include("/table/examples/parse.md") }}
+
+
+
+筛选列记忆功能
+
+即点击当前表格右上角筛选图标后,对表头进行显示隐藏勾选,再刷新页面依然保留当前筛选状态。
+
+
+
+{{- d.include("/table/examples/filter.md") }}
+
+
+
+选中行操作
+
+点击行任意处,通过行事件中执行相关选中方法,实现对整行的状态选中。*如下以「单选」行为例:*
+
+
+
+{{- d.include("/table/examples/setRowChecked.md") }}
+
+
+
+多级表头
+
+
+
+{{- d.include("/table/examples/theads.md") }}
+
+
+
+
+更多示例
+
+> - 🎉 不定期分享在 [Gitee Issues](https://gitee.com/layui/layui/issues)
+
diff --git a/docs/table/detail/options.ajax.md b/docs/table/detail/options.ajax.md
new file mode 100644
index 000000000..e86943aa0
--- /dev/null
+++ b/docs/table/detail/options.ajax.md
@@ -0,0 +1,226 @@
+
+
+
+
+
+
+
+ 属性名
+ 描述
+
+
+
+
+url
+
+
+发送异步请求的 URL。默认会自动传递两个参数:`?page=1&limit=30`(该参数可通过 `request` 属性自定义)
+ `page` 代表当前页码、`limit` 代表每页数据条数。
+
+
+
+
+method
+
+
+请求的方式,默认:`get`
+
+
+
+
+where
+
+
+请求的其他参数。如:`where: {token: 'sasasas', id: 123}`
+
+
+
+
+headers
+
+
+请求的数据头参数。如:`headers: {token: 'sasasas'}`
+
+
+
+
+contentType
+
+
+请求的内容编码类型。若要发送 `json` 内容,可设置:
+`contentType: 'application/json'`
+
+
+
+
+dataType 2.7+
+
+
+请求的数据类型,默认 `json`。
+
+
+
+
+jsonpCallback 2.7+
+
+
+设置当 `dataType: 'jsonp'` 时的回调函数名。
+
+
+
+
+request
+
+
+用于对默认的分页相关的请求参数 `page,limit` 重新设定名称。如:
+
+```
+request: {
+ pageName: 'curr', // 页码的参数名称,默认:page
+ limitName: 'nums' // 每页数据条数的参数名,默认:limit
+}
+```
+
+那么请求数据时的参数将会变为 `?curr=1&nums=30`
+
+
+
+
+
+
+[**parseData**](#options.parseData)
+
+
+
+
+
+ 数据格式解析的回调函数,用于将返回的任意数据格式解析成 table 组件规定的数据格式:
+
+
+```
+{
+ "code": 0,
+ "msg": "",
+ "count": 1000,
+ "data": [{}, {}]
+}
+```
+
+很多时候,您接口返回的数据格式并不一定都符合 table 默认规定的格式,比如:
+
+```
+{
+ "status": 0,
+ "message": "",
+ "total": 180,
+ "data": {
+ "item": [{}, {}]
+ }
+}
+```
+
+此时我们可以借助 `parseData` 回调函数将数据解析并转换为默认规定的格式:
+
+```
+table.render({
+ elem: '',
+ url: '',
+ parseData: function(res){ // res 即为原始返回的数据
+ return {
+ "code": res.status, // 解析接口状态
+ "msg": res.message, // 解析提示文本
+ "count": res.total, // 解析数据长度
+ "data": res.data.item // 解析数据列表
+ };
+ },
+ // … //其他参数
+});
+```
+
+该函数非常实用
+
+
+
+
+
+
+
+[**ajax**](#options.ajax) 2.12+
+
+
+
+
+
+ 自定义 ajax 请求,用于发送异步请求。
+
+
+```js
+table.render({
+ // 自定义 ajax 请求
+ // origOptions - 包含了原始的请求参数
+ // type - 执行 ajax 请求的来源,'table' 或 'treeNodes'
+ ajax: function (origOptions, type) {
+ $.ajax({
+ url: origOptions.url,
+ data: origOptions.data,
+ dataType: origOptions.dataType,
+ })
+ .done(function (data) {
+ // 调用原始的 success 回调
+ origOptions.success(data);
+ })
+ .fail(function (xhr, status, error) {
+ // 调用原始的 error 回调
+ origOptions.error(xhr, status, error);
+ })
+ .always(function () {
+ // 调用原始的 complete 回调
+ if (typeof origOptions.complete === "function") {
+ origOptions.complete();
+ }
+ });
+ }
+});
+
+```
+
+
+
+
+
+
+返回数据中的特定字段
+
+在返回的数据中,允许规定某些特定字段,以便 table 组件进行相应的特定解析。
+
+| 特定字段名 | 描述 | 读写状态 |
+| --- | --- | --- |
+| LAY_CHECKED | 当前行的选中状态 | 可读可写 |
+| LAY_DISABLED | 当前行是否禁止选择 | 可读可写 |
+| LAY_INDEX | 当前行下标。每页重新从零开始计算 | 只读 |
+| LAY_NUM | 当前行序号 | 只读 |
+| LAY_COL | 当前列的表头属性选项 | 只读 |
+
+示例一: 在返回的数据中设置特定字段:
+
+```
+{
+ "code": 0,
+ "count": 1000,
+ "data": [{},{
+ LAY_DISABLED: true
+ }]
+}
+```
+
+示例二: 在模板中读取特定字段示例:
+
+{{!
+```
+
+```
+!}}
+
diff --git a/docs/table/detail/options.cols.md b/docs/table/detail/options.cols.md
new file mode 100644
index 000000000..6c88fe860
--- /dev/null
+++ b/docs/table/detail/options.cols.md
@@ -0,0 +1,482 @@
+
+
+
+
+
+
+
+
+
+ 属性名
+ 描述
+ 类型
+ 默认值
+
+
+
+
+field
+
+
+设置字段名。通常是表格数据列的唯一标识
+
+
+string
+-
+
+
+title
+
+
+设置列的标题。
+
+
+string
+-
+
+
+fieldTitle 2.8+
+
+
+设置列的字段标题。该属性在筛选列和导出场景中优先级高于 `title` 属性
+
+
+string
+-
+
+
+width
+
+
+设置列宽。若不填写,则自动分配;若填写,则支持值为:*数字、百分比*。如:
+`width: 200` / `width: '30%'`
+
+
+number/string
+-
+
+
+minWidth
+
+
+设置当前列的最小宽度,一般用于列宽自动分配的情况。其优先级高于基础属性中的 `cellMinWidth`
+
+
+number
+
+
+`60`
+
+
+
+
+maxWidth 2.8+
+
+
+设置当前列的最大宽度。其优先级高于基础属性中的 `cellMaxWidth`
+
+
+number
+-
+
+
+expandedWidth 2.8.15+
+
+
+设置单元格被展开后的宽度。若设置的值的小于当前列宽,则展开后的列宽保持不变。注:当 `expandedMode` 属性为默认值时有效。
+
+
+number
+-
+
+
+expandedMode 2.8.17+
+
+
+用于设置所有单元格默认展开方式,可选值有:
+
+- `tips` 悬浮展开方式
+- `default` 多行展开方式(默认)
+
+优先级高于 `cellExpandedMode` 基础属性
+
+
+string
+-
+
+
+type
+
+
+设置列类型。可选值有:
+- `normal` 常规列,无需设定
+- `checkbox` 复选框列
+- `radio` 单选框列
+- `numbers` 序号列
+- `space` 空列
+
+
+string
+
+
+`normal`
+
+
+
+
+LAY_CHECKED
+
+
+设置全选状态,当列设置 `type: 'checkbox'` 时才有效。
+
+
+boolean
+
+
+`false`
+
+
+
+
+fixed
+
+
+设置固定列,即不跟随 table 横向滚动条而滚动。可选值有:
+- `left` 固定在左
+- `right` 固定在右
+
+多级表头设置固定列时,父列和子列均需设置。
+
+
+string
+-
+
+
+
+
+[templet](#cols.templet)
+
+
+
+
+
+ 设置列的自定义模板,核心属性。模板遵循
laytpl 组件语法。
+
+
+ `templet` 提供了三种使用方式,选择任一用法即可:
+
+- **设置模版选择器**
+
+{{!
+```
+
+
+
+```
+
+```
+table.render({
+ cols: [[
+ {field: 'title', templet: '#TPL-demo-title'}
+ // …
+ ]],
+ // …
+});
+```
+!}}
+
+- **设置模板内容**
+
+{{!
+```
+table.render({
+ cols: [[
+ {field: 'title', templet: ''}
+ // …
+ ]],
+ // …
+});
+```
+!}}
+
+- **设置模板函数**
+
+函数将返回一个 `d` 参数,包含当前行数据及特定的额外字段。
+```
+table.render({
+ cols: [[
+ {field: 'title', templet: function(d){
+ console.log(d); // 得到当前行数据
+ console.log(this); // 得到表头当前列配置项
+ console.log(d.LAY_NUM); // 得到序号。或其他特定字段
+
+ // 返回模板内容
+ return ''+ d.title +' '
+ }}
+ // …
+ ]],
+ // …
+});
+```
+
+
+
+
+exportTemplet 2.6.9+
+
+
+
+
+设置表格导出时的模板,用法同 `templet` 属性。当 `templet` 指向的模板内容较复杂时建议使用,如下以模板存在 `select` 元素为例:
+
+
+
+```
+exportTemplet: function(d, obj){
+ // 当前 td
+ var td = obj.td(this.field);
+ // 返回 select 选中值
+ return td.find('select').val();
+}
+```
+
+
+
+
+
+
+ [totalRow](#cols.totalRow)
+
+
+
+
+
+ 是否开启该列的自动合计功能,默认不开启。
+
+
+- **采用前端合计**
+
+{{!
+```
+// 开启并输出合计行前端合计结果
+totalRow: true
+
+// 开启并输出合计行自定义模板。此处 TOTAL_NUMS 即为合计结果的固定特定字段
+totalRow: '{{= d.TOTAL_NUMS }} 单位'
+// 取整或其他运算
+totalRow: '{{= parseInt(d.TOTAL_NUMS) }}'
+```
+!}}
+
+注意:*合计行模板仅支持字符写法,不支持函数写法,请勿与 `templet` 用法混淆。*
+
+- **采用后端合计**
+
+前端合计的数据有限,因此常需要后端直接返回合计结果,组件将优先读取。数据格式如下:
+
+```
+{
+ "code": 0,
+ "totalRow": {
+ "score": "777",
+ "experience": "999"
+ },
+ "data": [{}, {}],
+ "msg": "",
+ "count": 1000
+}
+```
+
+在合计行自定义模板中输出后端返回的合计数据
+
+{{!
+```
+// 获取后端接口返回数据中的统计字段。此处 TOTAL_ROW 即对应返回据中的 totalRow
+totalRow: '分数:{{= d.TOTAL_ROW.score }}'
+```
+!}}
+
+如上,在 `totalRow` 中返回所需统计的列字段名和值即可。
+`totalRow` 字段同样可以通过 `parseData` 回调来解析成为 table 组件所规定的数据格式。
+
+
+
+
+
+
+
+[edit](#cols.edit)
+
+
+
+
+
+ 用于对列所在的单元格开启编辑功能。可选值有:
+
+
+- `edit: 'text'` 单行输入模式
+- `edit: 'textarea'` 多行输入模式 2.7+
+
+**函数写法** 2.7+
+
+```
+edit: function(d){
+ // d 即为当前行数据,此时可根据行相关字段来开启该行是否编辑的权限
+ if(d.editable){ // editable 为任意字段名
+ return 'text'; // 编辑模式
+ }
+}
+```
+
+
+
+string function
+
+
+`false`
+
+
+
+
+hide
+
+
+是否初始隐藏列
+
+
+boolean
+
+
+`false`
+
+
+
+
+ignoreExport 2.8.3+
+
+
+是否导出时忽略该列。支持以下可选值:
+
+- `true` : 忽略导出
+- `false` : 强制导出,对所有列适用
+- `null` : 只对常规列导出(默认)
+
+
+boolean
+-
+
+
+escape
+
+
+是否对当前列进行内容编码(转义 html),优先级大于基础属性中的 `escape`。
+
+
+boolean
+
+
+`true`
+
+
+
+
+sort
+
+
+是否开启列的排序功能。
+注意:不推荐对值同时存在“数字和普通字符”的列开启排序,因为会进入字典序排序计算中 ,如:`'张三' > '2' > '100'`,这可能并不是你想要的结果,但字典序排列采用的是 `ASCII` 码比对。
+
+
+boolean
+
+
+`false`
+
+
+
+
+unresize
+
+
+是否禁用拖拽列宽。默认情况下会根据列类型 `type` 属性来决定是否禁用,如复选框列,会自动禁用。而其它普通列,默认允许拖拽列宽,当然你也可以设置 true 来禁用该功能。
+
+
+boolean
+
+
+`false`
+
+
+
+
+event
+
+
+自定义单元格点击事件名,以便在 [单元格工具事件](#on-tool) 中完成对该单元格的事件处理。
+
+
+string
+-
+
+
+style
+
+
+自定义单元格样式。可传入任意的 CSS 内容,如:`style: 'font-size: 13px; color: red;'`
+
+
+string
+-
+
+
+align
+
+
+单元格排列方式。可选值有:`left` | `center` | `right`
+
+
+string
+
+
+`left`
+
+
+
+
+colspan
+
+
+单元格所占列数。一般用于多级表头
+
+
+number
+
+
+`1`
+
+
+
+
+rowspan
+
+
+单元格所占行数。一般用于多级表头
+
+
+number
+
+
+`1`
+
+
+
+
+
+
diff --git a/docs/table/detail/options.md b/docs/table/detail/options.md
new file mode 100644
index 000000000..2bf543460
--- /dev/null
+++ b/docs/table/detail/options.md
@@ -0,0 +1,606 @@
+
+
+
+
+
+
+
+
+
+ 属性名
+ 描述
+ 类型
+ 默认值
+
+
+
+
+elem
+绑定原始 table 元素,方法渲染方式必填。
+string/DOM
+-
+
+
+
+
+[url](#options.ajax)
+
+
+
+
+发送异步请求的 URL。更多异步相关属性见 : [#异步属性](#options.ajax)
+
+
+-
+-
+
+
+
+
+[cols](#options.cols)
+
+
+
+
+表头属性集,通过二维数组定义多级表头。方法渲染时必填。 更多表头属性见 : [#表头属性](#options.cols)
+
+
+array
+-
+
+
+ data
+
+
+直接赋值数据。既适用于只展示一页数据,也能对一段已知数据进行多页展示。该属性与 `url` 属性只能二选一。
+
+
+
+**注**:当设置 `data` 模式时,`count` 的值取 `data.length`,即对一段已知数据进行分页展示。 此时在 `page` 属性中设置 `count` 无效。 若要在同一页显示所有数据,可将 `limit` 设置成 `data.length`,即与 `count` 等同即可,那么默认的分页栏只会显示 1 页,若要自定义分页结构,可通过 `pagebar` 属性结合 `laypage` 组件来重新自定义分页排版。
+
+
+ array
+ -
+
+
+ id
+
+
+设定实例唯一索引,以便用于其他方法对 table 实例进行相关操作。若该属性未设置,则默认从 `elem` 属性绑定的原始 table 元素中的 `id` 属性值中获取。
+
+
+string
+-
+
+
+toolbar
+
+
+开启表格头部工具栏。支持以下几种值写法:
+
+- `toolbar: '#template-id'` 自定义工具栏模板选择器
+- `toolbar: 'xxx
'` 直接传入模板字符
+- `toolbar: true` 仅开启工具栏右侧,不显示左侧模板
+- `toolbar: 'default'` 开启工具栏并显示默认模板
+
+
+string boolean
+
+
+`false`
+
+
+
+
+
+
+[defaultToolbar](#options.defaultToolbar)
+
+
+
+
+
+ 设置头部工具栏右上角工具图标,值为一个数组,图标将根据数组值的顺序排列。
+
+
+**默认内置工具**:
+
+```js
+defaultToolbar: [
+ 'filter', // 列筛选
+ 'exports', // 导出
+ 'print' // 打印
+]
+```
+
+**重写内置工具** 2.9.12+ ,以自定义导出为例:
+
+
+
+
+```js
+defaultToolbar: [
+ 'filter',
+ {
+ name: 'exports',
+ onClick: function(obj) {
+ // 获得数据并清除临时字段
+ var data = table.clearCacheKey(obj.data);
+ // 当前示例配置项
+ var options = obj.config;
+
+ // 弹出面板
+ obj.openPanel({
+ list: [ // 列表
+ '
导出 CSV 文件 ',
+ '导出 XLSX 文件 '
+ ].join(''),
+ done: function(panel, list) { // 操作列表
+ list.on('click', function() {
+ var type = $(this).data('type')
+ if (type === 'csv') {
+ // 调用内置导出方法
+ table.exportFile(options.id, null, type);
+ } else if(type === 'xlsx') {
+ // 自助处理导出 - 如借助 sheetjs 库或服务端导出
+ // …
+ }
+ });
+ }
+ });
+ }
+ },
+ 'print'
+]
+```
+
+
+
+**扩展工具图标**:
+
+```js
+defaultToolbar: [
+ 'filter', 'exports', 'print', // 内置工具
+ {
+ // 扩展工具
+ title: '提示', // 标题
+ name: 'tips', // name
+ layEvent: 'LAYTABLE_TIPS', // 事件标识
+ icon: 'lay-icon-tips', // 图标 className
+ onClick: function(obj) { // 点击事件 - 2.9.12+
+ console.log(obj); // 查看返回的对象成员
+ }
+ }
+]
+```
+
+
+
+
+width
+设置容器宽度,默认自适应。
+number
+-
+
+
+
+
+[height](#options.height)
+
+
+
+
+
+ 设置表格容器高度,默认自适应。其他可选值的规则如下:
+
+
+- `height: 315` 设置固定高度
+- `height: 'full-30'` 设置相对可视屏幕的高度铺满。这是一个特定的语法格式:`full` 表示铺满;后面的数字表示当前 table 之外的元素占用的高度,如:表格头部到页面最顶部*加*表格底部距离页面最底部的“距离和”
+- `height: '#id-30'` 设置相对父元素的高度铺满,其中 `#id` 即父元素的 ID 选择器,其计算原理和上述 `full` 相同。
+
+**函数写法** 2.9.1+
+
+当需要动态改变表格高度时建议使用,如下以等效 `full-xx` 的写法为例:
+
+```js
+height: function(){
+ // 自定义其他区域的高度
+ var otherHeight = $('#search-content').outerHeight();
+ return $(window).height() - otherHeight; // 返回 number 类型
+}
+```
+
+
+
+
+maxHeight 2.8+
+
+
+设置表格容器的最大高度,设置该属性后,`height` 属性将被认定为默认的自适应值。
+
+
+number
+-
+
+
+cellMinWidth
+
+
+设置所有普通单元格的最小宽度,一般用于列宽自动分配的情况。其优先级低于表头属性中的 `minWidth`
+
+
+number
+
+
+`60`
+
+
+
+
+cellMaxWidth 2.8+
+
+
+设置所有普通单元格的最大宽度。其优先级低于表头属性中的 `maxWidth`
+
+
+number
+-
+
+
+lineStyle 2.7+
+
+
+用于定义表格的多行样式,如每行的高度等。该参数一旦设置,单元格将会开启多行模式,且鼠标 hover 时会通过显示滚动条的方式查看到更多内容。 请按实际场景使用。 示例:`lineStyle: 'height: 95px;'`
+
+
+string
+-
+
+
+syncFixedRowHeight 2.12+ 实验性
+
+
+是否强制计算表格主区域的行高度并同步到固定列区域。开启后会对表格性能有一定的影响,仅适用于行高度自适应的场景。
+该功能使用 [ResizeObserver](https://developer.mozilla.org/zh-CN/docs/Web/API/ResizeObserver) 实现,如果你的浏览器不支持 `ResizeObserver`,可以尝试添加 [polyfill](https://github.com/que-etc/resize-observer-polyfill) 来解决兼容性问题。
+
+
+boolean
+-
+
+
+className 2.7+
+用于给表格主容器追加 css 类名,以便更好地扩展表格样式
+string
+-
+
+
+css 2.7+
+
+
+用于给当前表格主容器直接设定 css 样式,样式值只会对所在容器有效,不会影响其他表格实例。如:`css: '.lay-table-page{text-align: right;}'`
+
+
+string
+-
+
+
+cellExpandedMode 2.8.17+
+
+
+用于设置所有单元格默认展开方式,可选值有:
+
+- `tips` 悬浮展开方式
+- `default` 多行展开方式(默认)
+
+
+string
+-
+
+
+cellExpandedWidth 2.8.17+
+
+
+用于设置所有单元格默认展开后的宽度。当 `cellExpandedMode` 属性为默认值时有效。
+
+
+number
+
+
+`60`
+
+
+
+
+escape 2.6+
+是否开启对内容的编码(转义 html)
+boolean
+
+
+`true`
+
+
+
+
+totalRow
+是否开启合计行区域
+string
+
+
+`false`
+
+
+
+
+page
+
+
+用于开启分页。
+支持传入 [laypage](../laypage/#options) 组件的基础属性(jump,elem 除外)
+
+
+boolean object
+
+
+`false`
+
+
+
+
+pagebar 2.7+
+
+
+用于开启分页区域的自定义模板,用法同 `toolbar` 属性。
+
+
+string
+-
+
+
+limit
+
+
+每页显示的条数。值需对应 limits 参数的选项。优先级低于 `page` 属性中的 `limit` 属性。
+
+
+number
+
+
+`10`
+
+
+
+
+limits
+每页条数的选择项。
+array
+
+
+`[10,…,90]`
+
+
+
+
+loading
+
+
+设置数据请求时的加载动画,需开启 `url` 选项才生效。
+
+- 若值为 `boolean` 类型,表示是否显示加载条,如:
+```
+loading: true // 显示默认加载条
+loading: false // 禁用加载条
+```
+
+- 若值为 `string` 类型 2.9.10+ ,表示自定义加载模板,此时可添加任意动画元素,如:
+```
+loading: ' '
+```
+
+
+boolean string
+
+
+`true`
+
+
+
+
+scrollPos 2.7+
+
+
+用于设置重载数据或切换分页时的滚动条位置状态。可选值:
+- `fixed` 重载数据时,保持滚动条位置不变
+- `reset` 重载数据时,滚动条位置恢复置顶
+- `default` 默认方式,无需设置。即重载数据或切换分页时,纵向滚动条置顶,横向滚动条位置不变。
+
+
+string
+-
+
+
+editTrigger 2.7+
+
+
+是用于设定单元格编辑的事件触发方式。如双击: `dblclick`
+
+
+string
+
+
+`click`
+
+
+
+
+title
+定义 table 的大标题(在文件导出等地方会用到)
+string
+-
+
+
+text
+自定义文本,如空数据时的异常提示等。
+object
+
+
+ 查看默认值
+
+ `text: {none: '无数据'}`
+
+
+
+autoSort
+
+
+是否由组件自动进行前端排序。若为 `false`,则需自主排序,即由后端直接返回排序好的数据。[#详细用法](#on-sort)
+
+
+boolean
+
+
+`true`
+
+
+
+
+initSort
+
+
+初始排序状态。用于在数据表格渲染完毕时,按某个字段排序显示。它接受一个 `object` 类型的值,包含属性有:
+- `field` 排序字段。对应 `cols` 设定的各字段名
+- `type` 排序方式。可选值 : `'asc','desc',null`,即:`升序、降序、默认`
+
+```
+initSort: {
+ field: 'id', // 按 id 字段排序
+ type: 'desc' // 降序排序
+}
+```
+
+
+object
+-
+
+
+skin
+
+
+设置表格边框风格。可选值:`grid`\|`line`\|`row`\|`nob`
+
+
+string
+
+
+`grid`
+
+
+
+
+size
+
+
+设置表格其他尺寸。可选值:`sm`\|`md`|`lg`
+
+
+string
+
+
+`md`
+
+
+
+
+even
+
+
+是否开启隔行背景。
+
+
+string
+
+
+`false`
+
+
+
+
+
+
+[before](#options.before) 2.7+
+
+
+
+
+
+数据渲染之前的回调函数。
+
+
+```
+table.render({
+ before: function(options){
+ console.log(options); // 当前实例属性选项
+ options.where.abc = 123; // 修改或额外追加 where 属性
+ },
+ // … // 其它属性
+});
+```
+
+
+
+
+
+
+[done](#options.done)
+
+
+
+
+
+ 数据渲染完毕的回调函数。返回的参数如下:
+
+
+```
+table.render({
+ done: function(res, curr, count, origin){
+ console.log(res); // 得到当前渲染的数据
+ console.log(curr); // 得到当前页码
+ console.log(count); // 得到数据总量
+ console.log(origin); // 回调函数所执行的来源 --- 2.8.7+
+ },
+ // … // 其它属性
+});
+```
+
+
+
+
+error 2.6+
+
+
+数据请求失败的回调函数。返回两个参数:错误对象、内容。
+
+```
+error: function(e, msg) {
+ console.log(e, msg)
+}
+```
+
+
+
+
+complete 2.8.18+
+
+
+数据接口请求完成后执行,无论成功还是失败均会触发
+
+```
+complete: function(xhr, ts) {
+ console.log(xhr, ts)
+}
+```
+
+
+
+
+
+
diff --git a/docs/table/examples/autoRender.md b/docs/table/examples/autoRender.md
new file mode 100644
index 000000000..32cf57e90
--- /dev/null
+++ b/docs/table/examples/autoRender.md
@@ -0,0 +1,17 @@
+
+
+
+ ID
+ 用户名
+ 性别
+ 城市
+ 签名
+ 积分
+ 评分
+ 职业
+
+
+
+
+
+
diff --git a/docs/table/examples/css.md b/docs/table/examples/css.md
new file mode 100644
index 000000000..4b5e62002
--- /dev/null
+++ b/docs/table/examples/css.md
@@ -0,0 +1,84 @@
+
+
+
+
+ table 自定义样式 - Layui
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/table/examples/data.md b/docs/table/examples/data.md
new file mode 100644
index 000000000..8b4f634b2
--- /dev/null
+++ b/docs/table/examples/data.md
@@ -0,0 +1,85 @@
+
+
+
+
diff --git a/docs/table/examples/demo.md b/docs/table/examples/demo.md
new file mode 100644
index 000000000..d717c1086
--- /dev/null
+++ b/docs/table/examples/demo.md
@@ -0,0 +1,379 @@
+
+
+
+
+ table 组件综合演示 - Layui
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/table/examples/editModes.md b/docs/table/examples/editModes.md
new file mode 100644
index 000000000..5cc6cbe50
--- /dev/null
+++ b/docs/table/examples/editModes.md
@@ -0,0 +1,170 @@
+
+{{!
+
+
+
+
+
+
+
+!}}
+
+
+
+
diff --git a/docs/table/examples/editable.md b/docs/table/examples/editable.md
new file mode 100644
index 000000000..27cee60a0
--- /dev/null
+++ b/docs/table/examples/editable.md
@@ -0,0 +1,59 @@
+
+
+
+
+
diff --git a/docs/table/examples/filter.md b/docs/table/examples/filter.md
new file mode 100644
index 000000000..144b464b5
--- /dev/null
+++ b/docs/table/examples/filter.md
@@ -0,0 +1,49 @@
+
+
+
+
+
diff --git a/docs/table/examples/init.md b/docs/table/examples/init.md
new file mode 100644
index 000000000..d87178393
--- /dev/null
+++ b/docs/table/examples/init.md
@@ -0,0 +1,48 @@
+
+ 转换为数据表格
+
+
+
+
+
+ 人物
+ 民族
+ 格言
+
+
+
+
+ 孔子
+ 华夏
+ 有朋自远方来,不亦乐乎
+
+
+ 孟子
+ 华夏
+ 穷则独善其身,达则兼济天下
+
+
+ 庄子
+ 华夏
+ 朴素而天下莫能与之争美
+
+
+
+
+
+
diff --git a/docs/table/examples/onrowContextmenu.md b/docs/table/examples/onrowContextmenu.md
new file mode 100644
index 000000000..00c51631a
--- /dev/null
+++ b/docs/table/examples/onrowContextmenu.md
@@ -0,0 +1,59 @@
+
+
+
+
+
diff --git a/docs/table/examples/page.md b/docs/table/examples/page.md
new file mode 100644
index 000000000..782c8f408
--- /dev/null
+++ b/docs/table/examples/page.md
@@ -0,0 +1,43 @@
+
+
+
+
+
+
diff --git a/docs/table/examples/parse.md b/docs/table/examples/parse.md
new file mode 100644
index 000000000..f691f9207
--- /dev/null
+++ b/docs/table/examples/parse.md
@@ -0,0 +1,41 @@
+> 假设这是一段数据源:/static/json/2/table/demo3.json
+ 尽管它并不符合 table 组件默认规定的数据格式([#详见](#options-async-data)),但可以通过 parseData 回调将其进行转换。
+
+
+
+
+
+
diff --git a/docs/table/examples/search.md b/docs/table/examples/search.md
new file mode 100644
index 000000000..0521beb86
--- /dev/null
+++ b/docs/table/examples/search.md
@@ -0,0 +1,78 @@
+
+
+
+
+
+ Search
+ Clear
+
+
+
+
+
+
+
+
diff --git a/docs/table/examples/setRowChecked.md b/docs/table/examples/setRowChecked.md
new file mode 100644
index 000000000..93875a684
--- /dev/null
+++ b/docs/table/examples/setRowChecked.md
@@ -0,0 +1,62 @@
+
+
+
+
+
+
diff --git a/docs/table/examples/static.md b/docs/table/examples/static.md
new file mode 100644
index 000000000..6d39a95b8
--- /dev/null
+++ b/docs/table/examples/static.md
@@ -0,0 +1,207 @@
+默认风格:
+
+
+
+
+
+
+
+
+
+ 人物
+ 民族
+ 格言
+
+
+
+
+ 孔子
+ 华夏
+ 有朋自远方来,不亦乐乎
+
+
+ 孟子
+ 华夏
+ 穷则独善其身,达则兼济天下
+
+
+
+
+行边框表格:
+
+
+
+
+
+
+
+
+
+ 人物
+ 民族
+ 格言
+
+
+
+
+ 孔子
+ 华夏
+ 有朋自远方来,不亦乐乎
+
+
+ 孟子
+ 华夏
+ 穷则独善其身,达则兼济天下
+
+
+
+
+列边框表格:
+
+
+
+
+
+
+
+
+
+ 人物
+ 民族
+ 格言
+
+
+
+
+ 孔子
+ 华夏
+ 有朋自远方来,不亦乐乎
+
+
+ 孟子
+ 华夏
+ 穷则独善其身,达则兼济天下
+
+
+
+
+无边框表格:
+
+
+
+
+
+
+
+
+
+ 人物
+ 民族
+ 格言
+
+
+
+
+ 孔子
+ 华夏
+ 有朋自远方来,不亦乐乎
+
+
+ 孟子
+ 华夏
+ 穷则独善其身,达则兼济天下
+
+
+
+
+小尺寸表格:
+
+
+
+
+
+
+
+
+
+ 人物
+ 民族
+ 格言
+
+
+
+
+ 孔子
+ 华夏
+ 有朋自远方来,不亦乐乎
+
+
+ 孟子
+ 华夏
+ 穷则独善其身,达则兼济天下
+
+
+
+
+大尺寸表格:
+
+
+
+
+
+
+
+
+
+ 人物
+ 民族
+ 格言
+
+
+
+
+ 孔子
+ 华夏
+ 有朋自远方来,不亦乐乎
+
+
+ 孟子
+ 华夏
+ 穷则独善其身,达则兼济天下
+
+
+
+
+开启偶数行背景色:
+
+
+
+
+
+
+
+
+
+ 人物
+ 民族
+ 格言
+
+
+
+
+ 孔子
+ 华夏
+ 有朋自远方来,不亦乐乎
+
+
+ 孟子
+ 华夏
+ 穷则独善其身,达则兼济天下
+
+
+ 庄子
+ 华夏
+ 朴素而天下莫能与之争美
+
+
+
diff --git a/docs/table/examples/templet.md b/docs/table/examples/templet.md
new file mode 100644
index 000000000..03ab81020
--- /dev/null
+++ b/docs/table/examples/templet.md
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/table/examples/theads.md b/docs/table/examples/theads.md
new file mode 100644
index 000000000..ff444e07f
--- /dev/null
+++ b/docs/table/examples/theads.md
@@ -0,0 +1,54 @@
+常用两级表头:
+
+
+
+
+
+ 联系人
+ 地址
+ 数量
+ 操作
+
+
+ 省
+ 市
+ 区
+
+
+
+
+更多级表头(支持无限极):
+
+
+
+
+ 联系人
+ 数量
+ 地址1
+ 地址2
+ 操作
+
+
+ 省
+ 市
+ 详细
+ 省
+ 市
+
+
+ 街道
+ 小区
+ 单元
+
+
+
+
+
+
+
+
diff --git a/docs/table/index.md b/docs/table/index.md
new file mode 100644
index 000000000..4850b4e0e
--- /dev/null
+++ b/docs/table/index.md
@@ -0,0 +1,1004 @@
+---
+title: 表格组件 table
+toc: true
+---
+
+# 表格组件 🔥
+
+> 表格组件 `table` 是 Layui 中使用率极高的一个组件,它以表格的承载方式对数据进行渲染、重载、排序、统计、分页等等一系列交互操作,并提供了丰富的 API 用于扩展,基本涵盖了日常业务所涉及的大部分需求。
+
+示例
+
+以下所有示例中演示的数据均为「静态模拟数据」,实际使用时换成您的真实接口即可。
+
+
+
+
+{{- d.include("/table/detail/demo.md") }}
+
+
+API
+
+| API | 描述 |
+| --- | --- |
+| var table = layui.table | 获得 `table` 模块。 |
+| [table.set(options)](#set) | 设定全局默认属性项。 |
+| [table.render(options)](#render) | table 组件渲染,核心方法。 |
+| [table.init(filter, options)](#table.init) | 初始化渲染静态表格。 |
+| [table.reload(id, options, deep)](#table.reload) | 表格完整重载。 |
+| [table.reloadData(id, options, deep)](#table.reloadData) 2.7+ | 表格数据重载。 |
+| [table.renderData(id)](#table.renderData) 2.8.5+ | 重新渲染数据。 |
+| [table.updateRow(id, opts)](#table.updateRow) 2.9.4+ | 更新指定行数据。 |
+| [table.checkStatus(id)](#table.checkStatus) | 获取选中行相关数据。 |
+| [table.setRowChecked(id, opts)](#table.setRowChecked) 2.8+ | 设置行选中状态。 |
+| [table.getData(id)](#table.getData) | 获取当前页所有行表格数据。 |
+| [table.cache](#table.cache) | 获取表格缓存数据集(包含特定字段)。 |
+| [table.resize(id)](#table.resize) | 重置表格尺寸。 |
+| [table.exportFile(id, data, opts)](#table.exportFile) | 导出表格数据到本地文件。 |
+| [table.getOptions(id)](#table.getOptions) 2.8+ | 获取表格实例配置项。 |
+| [table.hideCol(id, cols)](#table.hideCol) 2.8+ | 设置表格列的显示隐藏属性。 |
+| [table.on(\'event(filter)\', callback)](#table.on) | table 相关事件。 |
+
+
+全局设置
+
+- 参数 `options` : 基础属性选项。[#详见属性](#options)
+
+该方法主要用于初始化设置属性默认值。实际应用时,必须先设置该方法,再执行渲染、重载等操作。
+
+```js
+layui.use(function(){
+ var table = layui.table;
+ // 全局设置
+ table.set({
+ headers: {token: '123'}
+ });
+ // 渲染
+ table.render(options);
+});
+```
+
+
+渲染
+
+table 提供了以下三种渲染模式,在实际使用时,一般按情况选择其中一种即可。
+
+| 渲染方式 | 描述 |
+| --- | --- |
+| [方法配置渲染](#table.render) | 通过 table 组件提供的核心方法 `table.render(options)` 完成的渲染。推荐 |
+| [模板配置渲染](#view-render) | 通过 `` 标签的 `lay-options="{}"` 属性定义模板,组件自动对其进行解析并完成渲染。 |
+| [静态表格渲染](#table.init) | 对一段已经包含数据内容的静态表格进行动态化转换,使其具备 table 组件的相关功能。 |
+
+
+方法配置渲染
+
+`table.render(options);`
+
+- 参数 `options` : 基础属性选项。[#详见属性](#options)
+
+该方法返回当前实例对象,包含可操作当前表格的一些成员方法。
+
+```html
+
+
+
+
+```
+
+模板配置渲染
+
+在 `` 元素中直接书写 `lay-options="{}"` 属性,组件将自动对其进行解析并完成渲染。
+
+```
+
+
+```
+
+> 2.8 之前版本通过 `lay-data="{}"` 定义属性选项;
+> 2.8+ 版本推荐采用 `lay-options`,但同时兼容 `lay-data`。
+
+
+静态表格渲染
+
+`table.init(filter, options);`
+
+- 参数 `filter` : `` 元素对应的 `lay-filter` 属性值
+- 参数 `options` : 基础属性选项。[#详见属性](#options)
+
+该方法用于将已输出在页面中的静态表格内容转换为动态 table 组件。[#参考相关示例](#demo-init)
+
+```html
+
+
+
+
+```
+
+属性 🔥
+
+属性是指 table *渲染、重载* 时的配置选项(`options`),它本身是一个 `object` 参数。如:
+
+```
+// 渲染
+table.render({
+ // options
+ elem: '',
+ cols: [[]],
+ // …
+});
+// 重载
+table.reload(id, {
+ // options
+});
+
+若为模板配置渲染,则 lay-options 或 lay-data 的属性值即为属性的配置选项(:
+
+```
+
+table 的属性众多,我们大致分为以下几种:
+
+| 属性类别 | 描述 |
+| --- | --- |
+| [基础属性](#options) | - |
+| [异步属性](#options.ajax) | 用于和异步数据请求相关的基础属性,由于相关属性成员较多,所以单独提取介绍。 |
+| [表头属性](#options.cols) | 基础属性 `cols` 的子属性集。 |
+
+基础属性
+
+
+{{- d.include("/table/detail/options.md") }}
+
+
+异步属性
+
+异步属性本质也是基础属性,当开启 `url` 属性时才有效,由于相关属性成员较多,所以单独提取介绍。
+
+
+{{- d.include("/table/detail/options.ajax.md") }}
+
+
+表头属性
+
+表头属性是基础属性 `cols` 的子集,其使用频率甚至超过基础属性本身。
+
+
+{{- d.include("/table/detail/options.cols.md") }}
+
+
+重载
+
+即对一段已经渲染好的表格重新设置属性并渲染,可分为以下几种重载方式:
+
+| 重载方式 | API |
+| --- | --- |
+| [完整重载](#table.reload) | [table.reload(id, options, deep)](#table.reload) |
+| [仅数据重载](#table.reloadData) | [table.reloadData(id, options, deep)](#table.reloadData) |
+
+重载的使用方式完全相同,区别只是在于参与重载时的属性差异及其对应的效果差异。一般按照实际需求选择使用。
+
+
+完整重载
+
+`table.reload(id, options, deep);`
+
+- 参数 `id` : table 渲染时的 `id` 属性值
+- 参数 `options` : 为基础属性选项
+- 参数 `deep` 2.6+ : 是否采用深度重载(即重载时始终携带初始时及上一次重载时的参数),默认 false。2.6 之前版本的 table.reload() 方法兼容性说明
+
+
+
+
由于 2.6 之前的版本是采用深度重载,所以如果您之前利用了该机制,那么升级 Layui 时,需通过以下任一方式进行相应的兼容性适配:
+
方法一:
+
追加参数兼容:
table.reload(id, options, true);
+
方法二:
+
方法重写兼容。将以下代码放入您的公共 JS 代码中
+
// 对 2.6 之前版本的 table.reload() 方法兼容
+var tableReload = table.reload;
+table.reload = function(){
+ var args = Array.from(arguments);
+ args[2] === undefined && (args[2] = true);
+ return tableReload.apply(null, args);
+};
+
+
+
+该方法用于对表格的视图和数据在内的全部重载,所有属性均会参与到重载中,对应的表格会有一个直观的刷新效果。
+
+```
+// 渲染
+table.render({
+ elem: '', // 绑定元素选择器
+ id: 'test', // 自定义 id 索引
+ // 其他属性 …
+});
+
+// 完整重载 - 所有属性属性(options)均可参与到重载中
+table.reload('test', {
+ where: { // 传递数据异步请求时携带的字段
+ aaa: '111',
+ bbb: '222'
+ //…
+ },
+ height: 1000 // 重设高度
+});
+```
+
+
+仅数据重载 2.7+
+
+`table.reloadData(id, options, deep);`
+
+- 参数同 `table.reload(id, options, deep)` 参数
+
+该方法用于对表格的数据重载,与数据无关的属性不会参与到重载中。因此若只是更新数据,该方法可大幅提升体验。
+
+```
+// 渲染
+table.render({
+ elem: '', // 绑定元素选择器
+ id: 'test', // 自定义 id 索引
+ // 其他属性 …
+});
+
+// 数据重载 - 仅与数据相关的属性(options)能参与到重载中
+table.reloadData('test', {
+ where: {}, // 数据异步请求时携带的字段集 --- 属性设置有效,因属于数据相关属性
+ scrollPos: true, // 设定重载数据或切换分页时的滚动条的位置状态 --- 属性设置有效
+ // …
+ height: 2000 // 高度 --- 属性设置无效,因不属于数据相关属性
+});
+```
+
+重新渲染数据 2.8.5+
+
+`table.renderData(id);`
+- 参数 `id` : table 渲染时的 `id` 属性值
+
+该方法用于重新渲染数据,一般在修改 `table.cache` 后使用。
+
+```js
+// 渲染
+table.render({
+ elem: '', // 绑定元素选择器
+ id: 'test', // 自定义 id 索引
+ // 其他属性 …
+});
+// 获取当前实例的数据缓存
+var data = table.cache['test'];
+// 获取某行数据,并从 data 中移除该行
+var item = data.splice(index, 1) // index 为当前行下标,一般可在事件中通过 obj.index 得到
+// 将某行数据移动到另外某行
+data.splice(newIndex, 0, item[0]);
+// 根据 table.cache 重新渲染数据
+table.renderData('test');
+```
+
+更新指定行数据 2.9.4+
+
+`table.updateRow(id, opts);`
+- 参数 `id` : table 渲染时的 `id` 属性值
+- 参数 `opts` : 更新指定行时的可选属性,详见下表
+
+| opts | 描述 | 类型 | 默认值 |
+| --- | --- | --- | --- |
+| index | 行索引 | number | - |
+| data | 行数据 | object | - |
+| related | 是否更新其他包含自定义模板且可能有所关联的列视图 | boolean/function | - |
+
+该方法用于更新指定行数据。
+
+```js
+// 渲染
+table.render({
+ elem: '', // 绑定元素选择器
+ id: 'test', // 自定义 id 索引
+ // 其他属性 …
+});
+
+// 更新指定行数据
+table.updateRow('test', {
+ index: 0,
+ data: {
+ id: 1,
+ username: 'name'
+ }
+ // 是否更新关联的列视图
+ related: function(field, index){
+ return ['score', '5'].indexOf(field) !== -1;
+ }
+});
+```
+
+获取选中行
+
+`table.checkStatus(id);`
+- 参数 `id` : table 渲染时的 `id` 属性值
+
+该方法用于获取表格当前选中行相关数据
+
+```js
+// 渲染
+table.render({
+ elem: '', // 绑定元素选择器
+ id: 'test', // 自定义 id 索引
+ // 其他属性 …
+});
+
+// 获取选中行相关数据
+var tableStatus = table.checkStatus('test');
+console.log(tableStatus.data) // 选中行的数据
+console.log(tableStatus.data.length) // 选中行数量,可作为是否有选中行的条件
+console.log(tableStatus.dataCache) // 选中的原始缓存数据,包含内部特定字段 --- 2.9.17+
+console.log(tableStatus.isAll ) // 表格是否全选
+```
+
+设置行选中状态 2.8+
+
+`table.setRowChecked(id, opts);`
+- 参数 `id` : table 渲染时的 `id` 属性值
+- 参数 `opts` : 设置行选中时的可选属性,详见下表
+
+| opts | 描述 | 类型 | 默认值 |
+| --- | --- | --- | --- |
+| type | 选中方式。可选值: `checkbox,radio` | string | `checkbox` |
+| index | 选中行的下标。支持以下几种情况:若值为 `number` 类型,则表示行所在的数组下标(`0` 开头) 若值为 `array` 类型 2.9.1+ ,则表示多选下标。 若值为 `string` 类型,则可设置 `all` 操作全选。 | number array string | - |
+| checked | 选中状态值。 若传递该属性,则赋值固定值。 若不传递该属性(默认),则 `checkbox` 将在 `true\|false` 中自动切换值,而 `radio` 将赋值 `true` 固定值。2.8.4+ **注意**:若 `index` 指定为多选或全选,`checked` 应当显式传递固定值 | boolean | - |
+
+该方法用于设置行的选中样式及相关的特定属性值 `LAY_CHECKED`。
+
+```js
+// 渲染
+table.render({
+ elem: '', // 绑定元素选择器
+ id: 'test', // 自定义 id 索引
+ // 其他属性 …
+});
+
+// 设置某行选中
+table.setRowChecked('test', {
+ index: 0, // 选中行的下标。 0 表示第一行
+});
+
+// 批量选中行
+table.setRowChecked('test', {
+ index: [1,3,5] // 2.9.1+
+});
+
+// 取消选中行
+table.setRowChecked('test', {
+ index: 'all', // 所有行
+ checked: false // 此处若设置 true,则表示全选
+});
+```
+
+
+获取当前页接口数据
+
+`table.getData(id);`
+- 参数 `id` : table 渲染时的 `id` 属性值
+
+该方法用于获取表格当前页的数据,它对应的是接口返回的原始数据,不包含 table 组件内部的特定字段。
+
+```
+// 渲染
+table.render({
+ elem: '', // 绑定元素选择器
+ id: 'test', // 自定义 id 索引
+ // 其他属性 …
+});
+
+// 获取当前页接口数据
+var data = table.getData('test');
+console.log(data);
+```
+
+
+获取表格缓存数据集
+
+`var tableCache = table.cache;`
+
+`table.cache` 是一段存储当前页表格所有实例的当前页的临时数据,通过 id 作为索引,它包含接口返回的原始数据和组件内部的特定字段。 使用该静态属性可对表格数据进行*读写*操作。
+
+```
+// 渲染
+table.render({
+ elem: '', // 绑定元素选择器
+ id: 'test', // 自定义 id 索引
+ // 其他属性 …
+});
+
+// 获取对应 table 的临时数据
+var thisCache = table.cache['test'] || {};
+
+// 变更对应 table 的临时数据中的某个字段值
+thisCache.fieldName = 123;
+```
+
+
+重置尺寸
+
+`table.resize(id);`
+- 参数 `id` : table 渲染时的 `id` 属性值
+
+该方法用于重置表格尺寸和结构,其内部完成了*固定列高度平铺、动态分配列宽、容器滚动条宽高补丁* 等适配。它一般用于修复特殊情况下导致的列宽适配异常(如浏览器窗口尺寸改变导致的表格父容器宽度变化),以保证表格尺寸依旧能友好展示。
+
+
+```
+// 渲染
+table.render({
+ elem: '', // 绑定元素选择器
+ id: 'test', // 自定义 id 索引
+ // 其他属性 …
+});
+
+// 重置对应 table 的尺寸,一般写在表格外部容器宽高发生变化后的段落
+table.resize('test');
+```
+
+
+导出数据
+
+`table.exportFile(id, data, opts);`
+- 参数 `id` : table 渲染时的 `id` **或** 要导出的数据表头(当 `id` 为 `array` 类型时)。
+- 参数 `data` : 要导出的自定义数据,参数可选。
+- 参数 `opts` 2.7+ : 导出数据时的属性选项,支持: `type,title`。
+
+该方法用于外部导出对应 table 的数据和任意自定义数据。
+
+```
+// 渲染
+table.render({
+ elem: '', // 绑定元素选择器
+ id: 'test', // 自定义 id 索引
+ // 其他属性 …
+});
+
+// 外部导出对应 table 的数据
+table.exportFile('test');
+
+// 导出自定义数据
+table.exportFile(['名字','性别','年龄'], [
+ ['张三','男','20'],
+ ['李四','女','18'],
+ ['王五','女','19']
+], {
+ type: 'csv', // 导出的文件格式,支持: csv,xls
+ title: '导出的文件标题'
+});
+```
+
+获取配置项 2.8+
+
+`table.getOptions(id);`
+- 参数 `id` : table 渲染时的 `id` 属性值
+
+该方法用于外部获取对应 table 实例的属性选项。
+
+```
+// 渲染
+table.render({
+ elem: '', // 绑定元素选择器
+ id: 'test', // 自定义 id 索引
+ // 其他属性 …
+});
+
+// 获取配置项
+var thisOptions = table.getOptions('test');
+console.log(thisOptions);
+```
+
+设置列显示或隐藏 2.8+
+
+`table.hideCol(id, cols);`
+- 参数 `id` : table 渲染时的 `id` 属性值
+- 参数 `cols` : 设置列(表头)显示或隐藏状态
+
+该方法用于外部设置对应 table 列的显示与隐藏状态。
+
+```
+// 渲染
+table.render({
+ elem: '', // 绑定元素选择器
+ id: 'test', // 自定义 id 索引
+ // 其他属性 …
+});
+
+// 设置对应列的显示或隐藏
+table.hideCol('test', {
+ field: 'title', // 对应表头的 field 属性值
+ hide: true // `true` or `false`
+});
+
+// 同时设置多列的显示或隐藏
+table.hideCol('test', [{
+ field: 'title1',
+ hide: true
+}, {
+ field: 'title2',
+ hide: false
+}, {
+ field: 'title3',
+ hide: false
+}]);
+
+// 显示或隐藏全部列
+table.hideCol('test', false); // `true` or `false`
+```
+
+事件
+
+`table.on('event(filter)', callback);`
+
+- 参数 `event(filter)` 是事件的特定结构。 `event` 为事件名,支持的事件见下表。`filter` 为元素属性 `lay-filter` 对应的值。
+- 参数 `callback` 为事件执行时的回调函数,并返回一个包含各项成员的 `object` 类型的参数。
+
+| event | 描述 |
+| --- | --- |
+| [toolbar](#on-toolbar) | 头部工具栏事件 |
+| [sort](#on-sort) | 表头排序切换事件 |
+| [colTool](#on-colTool) 2.8.8+ | 表头自定义元素工具事件 |
+| [colResized](#on-colResized) 2.8+ | 列拖拽宽度后的事件 |
+| [colToggled](#on-colToggled) 2.8+ | 列筛选(显示或隐藏)后的事件 |
+| [row / rowDouble](#on-row) | 行单击和双击事件 |
+| [rowContextmenu](#on-rowContextmenu) 2.8+ | 行右键菜单事件 |
+| [edit](#on-edit) | 单元格编辑事件 |
+| [tool / toolDouble](#on-tool) 🔥 | 单元格工具事件。可在该事件中实现行的更新与删除操作。 |
+| [checkbox](#on-checkbox) | 复选框事件 |
+| [radio](#on-radio) | 单选框事件 |
+| [pagebar](#on-pagebar) 2.7+ | 尾部分页栏事件 |
+
+
+
+
+`table.on('toolbar(filter)', callback);`
+
+点击头部工具栏区域设定了属性为 `lay-event=""` 的元素时触发。如:
+
+```html
+
+
+
+
+
+
+
+
+```
+
+排序切换事件
+
+`table.on('sort(filter)', callback);`
+
+点击表头排序时触发,它通常在设置 `autoSort: false ` 基础属性时使用,以呈现后端的排序,而不是默认的前端排序。
+
+```js
+var table = layui.table;
+
+// 禁用前端自动排序,以便由服务端直接返回排序好的数据
+table.render({
+ elem: '#test',
+ autoSort: false, // 禁用前端自动排序。
+ // … // 其他属性
+});
+
+// 触发排序事件
+table.on('sort(test)', function(obj){
+ console.log(obj.field); // 当前排序的字段名
+ console.log(obj.type); // 当前排序类型:desc(降序)、asc(升序)、null(空对象,默认排序)
+ console.log(this); // 当前排序的 th 对象
+
+ // 尽管我们的 table 自带排序功能,但并没有请求服务端。
+ // 有些时候,你可能需要根据当前排序的字段,重新向后端发送请求,从而实现服务端排序,如:
+ table.reload('test', {
+ initSort: obj, // 记录初始排序,如果不设的话,将无法标记表头的排序状态。
+ where: { // 请求参数(注意:这里面的参数可任意定义,并非下面固定的格式)
+ field: obj.field, // 排序字段
+ order: obj.type // 排序方式
+ }
+ });
+});
+```
+
+
+
+`table.on('colTool(filter)', callback);`
+
+点击表头单元格中带有 `lay-event` 属性的自定义元素触发,可充分借助该事件扩展 table 更多的操作空间。
+
+```js
+var table = layui.table;
+
+// 渲染
+table.render({
+ elem: '#test',
+ cols: [[
+ {field:'username', title:'用户名 '
+ ]]
+ // … // 其他属性
+});
+
+// 表头自定义元素工具事件
+table.on('colTool(test)', function(obj){
+ var col = obj.col; // 获取当前列属性选项
+ var options = obj.config; // 获取当前表格基础属性选项
+ var layEvent = obj.event; // 获得自定义元素对应的 lay-event 属性值
+ console.log(obj); // 查看对象所有成员
+});
+```
+
+列拖拽宽度后的事件 2.8+
+
+`table.on('colResized(filter)', callback);`
+
+在表头列分割线拖拽宽度后触发。
+
+```js
+var table = layui.table;
+
+// 渲染
+table.render({
+ elem: '#test',
+ // … // 其他属性
+});
+
+// 列拖拽宽度后的事件
+table.on('colResized(test)', function(obj){
+ var col = obj.col; // 获取当前列属性选项
+ var options = obj.config; // 获取当前表格基础属性选项
+ console.log(obj); // 查看对象所有成员
+});
+```
+
+列筛选(显示或隐藏)后的事件 2.8+
+
+`table.on('colToggled(filter)', callback);`
+
+点击头部工具栏右上角的字段筛选列表时触发。
+
+```js
+var table = layui.table;
+
+// 渲染
+table.render({
+ elem: '#test',
+ // … // 其他属性
+});
+
+// 列筛选(显示或隐藏)后的事件
+table.on('colToggled(test)', function(obj){
+ var col = obj.col; // 获取当前列属性选项
+ var options = obj.config; // 获取当前表格基础属性选项
+ console.log(obj); // 查看对象所有成员
+});
+```
+
+
+行单击和双击事件
+
+- 行单击事件:`table.on('row(filter)', callback);`
+- 行双击事件:`table.on('rowDouble(filter)', callback);`
+
+单击或双击 table 行任意区域触发,两者用法相同。
+注2.8.4+ :在 table 模板中或任意内部元素中设置 `lay-unrow` 属性,可阻止该元素执行 `row` 事件
+
+```js
+var table = layui.table;
+
+// 渲染
+table.render({
+ elem: '#test',
+ // … // 其他属性
+});
+
+// 行单击事件
+table.on('row(test)', function(obj) {
+ var data = obj.data; // 得到当前行数据
+ var dataCache = obj.dataCache; // 得到当前行缓存数据,包含特定字段 --- 2.8.8+
+ var index = obj.index; // 得到当前行索引
+ var tr = obj.tr; // 得到当前行 元素的 jQuery 对象
+ var options = obj.config; // 获取当前表格基础属性选项
+ var e = obj.e; // 当前的 jQuery 事件对象 --- 2.9.14+
+
+ console.log('onrow', obj); // 查看返回对象的所有成员
+
+ // obj.del() // 删除当前行
+ // obj.update(fields, related); // 修改行数据
+ // obj.setRowChecked(opts); // 设置行选中状态
+});
+
+// 行双击事件
+table.on('rowDouble(test)', function(obj) {
+ console.log('onrowDouble', obj); // 查看返回对象的所有成员 - 同 row 事件
+});
+```
+
+
+
+`table.on('rowContextmenu(filter)', callback);`
+
+右键单击行时触发。
+
+
+
+{{- d.include("/table/examples/onrowContextmenu.md") }}
+
+
+
+单元格编辑事件
+
+`table.on('edit(filter)', callback);`
+
+单元格被编辑,且值发生改变时触发。
+
+```js
+var table = layui.table;
+var layer = layui.layer;
+
+// 单元格编辑事件
+table.on('edit(test)', function(obj){
+ var field = obj.field; // 得到修改的字段
+ var value = obj.value // 得到修改后的值
+ var oldValue = obj.oldValue // 得到修改前的值 -- v2.8.0 新增
+ var data = obj.data // 得到所在行所有键值
+ var col = obj.getCol(); // 得到当前列的表头配置属性 -- v2.8.0 新增
+ console.log(obj); // 查看对象所有成员
+
+ // 值的校验
+ if(value.replace(/\s/g, '') === ''){
+ layer.tips('值不能为空', this, {tips: 1});
+ return obj.reedit(); // 重新编辑 -- v2.8.0 新增
+ }
+
+ // 编辑后续操作,如提交更新请求,以完成真实的数据更新
+ // …
+
+ // 更新当前缓存数据
+ var update = {};
+ update[field] = value;
+ obj.update(update, true); // 参数 true 为 v2.7 新增功能,即同步更新其他包含自定义模板并可能存在关联的列视图
+});
+
+```
+
+
+
+
+- 单元格工具事件「单击触发」: `table.on('tool(filter)', callback);`
+- 单元格工具事件「双击触发」: `table.on('toolDouble(filter)', callback);`
+
+单击或双击单元格中带有 `lay-event=""` 属性的元素时触发。在表格主体的单元格中,经常需要进行很多的动态操作,比如编辑、删除等操作,这些均可以在单元格工具事件中完成。
+
+{{!
+```html
+
+
+
+
+
+
+
+```
+!}}
+
+复选框事件
+
+`table.on('checkbox(filter)', callback);`
+
+当 table 开启复选框,且点击复选框时触发。
+
+```js
+var table = layui.table;
+
+// 复选框事件
+table.on('checkbox(test)', function(obj){
+ console.log(obj); // 查看对象所有成员
+ console.log(obj.checked); // 当前是否选中状态
+ console.log(obj.data); // 选中行的相关数据
+ console.log(obj.type); // 若触发的是全选,则为:all;若触发的是单选,则为:one
+});
+```
+
+
+单选框事件
+
+`table.on('radio(filter)', callback);`
+
+当 table 开启单选框,且点击单选框时触发。
+
+```js
+var table = layui.table;
+
+// 单选框事件
+table.on('radio(test)', function(obj){
+ console.log(obj); // 当前行的一些常用操作集合
+ console.log(obj.checked); // 当前是否选中状态
+ console.log(obj.data); // 选中行的相关数据
+});
+```
+
+
+尾部分页栏事件 2.7+
+
+`table.on('pagebar(filter)', callback);`
+
+点击尾部分页栏自定义模板中属性为 `lay-event=""` 的元素时触发。用法跟 toolbar 完全一致。
+
+```js
+var table = layui.table;
+
+// 渲染
+table.render({
+ elem: '#demo',
+ pagebar: '#pagebarDemo' // 分页栏模板所在的选择器
+ // … // 其他参数
+});
+
+// 分页栏事件
+table.on('pagebar(test)', function(obj){
+ console.log(obj); // 查看对象所有成员
+ console.log(obj.config); // 当前实例的配置信息
+ console.log(obj.event); // 属性 lay-event 对应的值
+});
+```
+
+## 小贴士
+
+若表头数量太多及每页呈现的数据量太大,为了性能考虑,建议采用 [静态表格](#demo-static) 渲染,配合 [laypage](../laypage/#options) 组件实现分页。
+
+
+
+
+
+
diff --git a/docs/tabs/detail/demo.md b/docs/tabs/detail/demo.md
new file mode 100644
index 000000000..33fde0635
--- /dev/null
+++ b/docs/tabs/detail/demo.md
@@ -0,0 +1,80 @@
+动态操作
+
+
+
+{{- d.include("/tabs/examples/demo.md") }}
+
+
+
+方法渲染
+
+即通过方法设置 tabs 标签,而非默认的自动渲染页面中的 `class="lay-tabs"` 的容器模板。
+
+
+
+{{- d.include("/tabs/examples/method.md") }}
+
+
+
+卡片风格
+
+
+
+{{- d.include("/tabs/examples/card.md") }}
+
+
+
+自定义事件
+
+
+
+{{- d.include("/tabs/examples/trigger.md") }}
+
+
+
+打乱标签顺序
+
+
+
+{{- d.include("/tabs/examples/shuffle.md") }}
+
+
+
+通过 HASH 匹配选中标签
+
+切换 tabs 标签项后,地址栏同步 `hash` 值,当页面刷新时,tabs 仍保持对应的切换状态。
+
+
+
+{{- d.include("/tabs/examples/hash.md") }}
+
+
+
+标签嵌套
+
+
+
+{{- d.include("/tabs/examples/nest.md") }}
+
+
+
+给任意元素绑定 tabs 切换功能
+
+
+
+{{- d.include("/tabs/examples/custom.md") }}
+
+
+
diff --git a/docs/tabs/detail/options.md b/docs/tabs/detail/options.md
new file mode 100644
index 000000000..e2994ed55
--- /dev/null
+++ b/docs/tabs/detail/options.md
@@ -0,0 +1,160 @@
+
+
+
+
+
+
+
+
+
+ 属性名
+ 描述
+ 类型
+ 默认值
+
+
+
+
+elem
+
+
+组件渲染指定的目标元素选择器或 DOM 对象
+
+
+string/DOM
+-
+
+
+
+id
+
+
+组件渲染的唯一实例 ID
+
+
+string
+-
+
+
+className
+
+
+给主容器追加 CSS 类名,以便自定义样式
+
+
+string
+-
+
+
+trigger
+
+
+标签切换的触发事件
+
+
+boolean
+
+
+`click`
+
+
+
+
+headerMode
+
+
+标签头部的显示模式。可选值有:
+
+- `auto` 自动模式,根据标签头部是否溢出自动显示不同模式
+- `scroll` 始终滚动模式
+- `normal` 始终常规模式,不渲染头部滚动结构
+
+
+string
+
+
+`auto`
+
+
+
+
+index
+
+
+初始选中的标签索引或标签 `lay-id` 属性值
+
+
+number
+-
+
+
+closable
+
+
+是否开启标签项关闭功能
+
+
+boolean
+
+
+`false`
+
+
+
+
+header
+
+
+设置标签头部列表,通常在「非自动渲染」的场景下使用:
+
+**1. 方法渲染**
+
+若 `header` 传入一个数组,且成员值为对象,即为方法渲染时传入的头部列表数据。如:
+
+```js
+header: [
+ { title: 'Tab1' }, // 除 `title` 为必传项外,也可传入其他任意字段。
+ { title: 'Tab2' }
+]
+```
+
+**2. 任意元素渲染**
+
+若 `header` 传入一个数组,则成员值为元素选择器,即为绑定标签头部列表元素。如:
+
+```js
+header: ['#tabsHeader', '>li'],
+```
+
+
+
+
+body
+
+
+设置标签内容列表,通常在「非自动渲染」的场景下使用:
+
+**1. 方法渲染**
+
+若 `body` 传入一个数组,且成员值为对象,即为方法渲染时传入的标签内容列表数据。如:
+
+```js
+body: [
+ { content: 'Tab1' }, // `content` 为必传项
+ { content: 'Tab2' }
+]
+```
+
+**2. 任意元素渲染**
+
+若 `body` 传入一个数组,则成员值为元素选择器,即为绑定标签内容列表元素。如:
+
+```js
+body: ['#tabsBody', '>div'],
+```
+
+
+
+
+
+
diff --git a/docs/tabs/examples/beforeChange.md b/docs/tabs/examples/beforeChange.md
new file mode 100644
index 000000000..270dc4c3c
--- /dev/null
+++ b/docs/tabs/examples/beforeChange.md
@@ -0,0 +1,45 @@
+
+
+
+
Tab Content-1
+
Tab Content-2
+
Tab Content-3
+
Tab Content-4
+
Tab Content-5
+
Tab Content-6
+
+
+
+本示例演示:切换标签时,弹出确认提示。
+
+
+
+
diff --git a/docs/tabs/examples/beforeClose.md b/docs/tabs/examples/beforeClose.md
new file mode 100644
index 000000000..3a3ef045f
--- /dev/null
+++ b/docs/tabs/examples/beforeClose.md
@@ -0,0 +1,45 @@
+
+
+
+
Tab Content-1
+
Tab Content-2
+
Tab Content-3
+
Tab Content-4
+
Tab Content-5
+
Tab Content-6
+
+
+
+本示例演示:删除标签之前,弹出确认提示。
+
+
+
+
diff --git a/docs/tabs/examples/card.md b/docs/tabs/examples/card.md
new file mode 100644
index 000000000..d382bf849
--- /dev/null
+++ b/docs/tabs/examples/card.md
@@ -0,0 +1,55 @@
+#### 普通卡片
+
+
+
+
+
内容-1
+
内容-2
+
内容-3
+
内容-4
+
内容-5
+
内容-6
+
+
+
+#### 边框卡片
+
+
+
+
+
+
+
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+
+
+
+
2
+
3
+
4
+
5
+
6
+
+
+
+
+
diff --git a/docs/tabs/examples/custom.md b/docs/tabs/examples/custom.md
new file mode 100644
index 000000000..056d14960
--- /dev/null
+++ b/docs/tabs/examples/custom.md
@@ -0,0 +1,31 @@
+
+
+
+
+
内容 111
+
内容 222
+
内容 333
+
+
+
+
+
+
diff --git a/docs/tabs/examples/demo.md b/docs/tabs/examples/demo.md
new file mode 100644
index 000000000..cde188ce8
--- /dev/null
+++ b/docs/tabs/examples/demo.md
@@ -0,0 +1,114 @@
+
+
+
+
Tab Content-1
+
Tab Content-2
+
Tab Content-3
+
Tab Content-4
+
Tab Content-5
+
Tab Content-6
+
+
+
+🔔 操作提示:在「标签头部」点击鼠标右键,可开启标签操作的更多实用演示
+
+
+ 切换到:Tab3
+ 切换到:第 2 项
+ 关闭:Tab4
+ 关闭:第 2 项
+ 添加 Tab
+
+
+
+
+
diff --git a/docs/tabs/examples/hash.md b/docs/tabs/examples/hash.md
new file mode 100644
index 000000000..7bd6f3342
--- /dev/null
+++ b/docs/tabs/examples/hash.md
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
diff --git a/docs/tabs/examples/method.md b/docs/tabs/examples/method.md
new file mode 100644
index 000000000..2e01892c9
--- /dev/null
+++ b/docs/tabs/examples/method.md
@@ -0,0 +1,27 @@
+
+
+
+
+
diff --git a/docs/tabs/examples/nest.md b/docs/tabs/examples/nest.md
new file mode 100644
index 000000000..d01dd16b5
--- /dev/null
+++ b/docs/tabs/examples/nest.md
@@ -0,0 +1,41 @@
+
+
+
+
diff --git a/docs/tabs/examples/shuffle.md b/docs/tabs/examples/shuffle.md
new file mode 100644
index 000000000..64c87e134
--- /dev/null
+++ b/docs/tabs/examples/shuffle.md
@@ -0,0 +1,23 @@
+
+
+
+
Tab Content-1
+
Tab Content-2
+
Tab Content-3
+
Tab Content-4
+
Tab Content-5
+
Tab Content-6
+
+
+
+🔔 提示:即 tabs 能通过 `lay-id` 匹配对应的标签头和标签内容。
+
+
+
diff --git a/docs/tabs/examples/trigger.md b/docs/tabs/examples/trigger.md
new file mode 100644
index 000000000..8975f5a97
--- /dev/null
+++ b/docs/tabs/examples/trigger.md
@@ -0,0 +1,44 @@
+#### mouseenter 触发
+
+
+
+
+
内容-1
+
内容-2
+
内容-3
+
内容-4
+
内容-5
+
内容-6
+
+
+
+#### mousedown 触发
+
+
+
+
+
内容-1
+
内容-2
+
内容-3
+
内容-4
+
内容-5
+
内容-6
+
+
+
+
+
diff --git a/docs/tabs/index.md b/docs/tabs/index.md
new file mode 100644
index 000000000..041423788
--- /dev/null
+++ b/docs/tabs/index.md
@@ -0,0 +1,364 @@
+---
+title: 标签页组件 tabs
+toc: true
+---
+
+# 标签页组件 2.10+
+
+> `tabs` 是 2.10 版本新增的加强型组件,可替代原 `element` 模块中的 `tab` 组件。tabs 广泛应用于 Web 页面。
+
+示例
+
+
+
+
+{{- d.include("/tabs/detail/demo.md") }}
+
+
+API
+
+| API | 描述 |
+| --- | --- |
+| var tabs = layui.tabs | 获得 `tabs` 模块。|
+| [基础接口](../component/#export) | 该组件由 `component` 构建,因此继承其提供的基础接口。|
+| [tabs.render(options)](#render) | tabs 组件渲染,核心方法。|
+| [tabs.add(id, opts)](#add) | 新增一个标签项。|
+| [tabs.close(id, index, force)](#close) | 关闭指定的标签项。|
+| [tabs.closeMult(id, mode, index)](#closeMult) | 批量关闭标签项。|
+| [tabs.change(id, index, force)](#change) | 切换到指定的标签项。|
+| [tabs.data(id)](#data) | 获取当前标签页相关数据。|
+| [tabs.getHeaderItem(id, index)](#getHeaderItem) | 获取指定的标签头部项。|
+| [tabs.getBodyItem(id, index)](#getBodyItem) | 获取指定的标签内容项。|
+| [tabs.refresh(id)](#refresh) | 刷新标签视图。 |
+
+渲染
+
+`tabs.render(options)`
+
+- 参数 `options` : 基础属性选项。[#详见属性](#options)
+
+组件支持以下三种渲染方式:
+
+#### 1. 自动渲染
+
+tabs 组件会在元素加载完毕后,自动对 `class="lay-tabs"` 目标元素完成一次渲染,若无法找到默认的目标元素(如:动态插入的标签元素的场景),则可通过该方法完成对标签页的初始化渲染。
+
+```js
+// 对 class="lay-tabs" 所在标签进行初始化渲染
+tabs.render();
+```
+
+#### 2. 方法渲染
+
+通过方法动态渲染一个 tabs 组件,无需在 HTML 中书写标签页的 HTML 结构。
+
+```js
+
+
+
+```
+
+#### 3. 为任意元素渲染 tabs 功能
+
+当 `header` 和 `body` 参数传入元素选择器时,可为任意元素绑定标签切换功能。
+
+```js
+// 给任意元素绑定 Tab 功能
+tabs.render({
+ elem: '#demoTabs3', // 目标主容器选择器
+ header: ['#demoTabsHeader', '>button'], // 标签头部主元素选择器、标签头部列表选择器
+ body: ['#demoTabsBody', '>.test-item'] // 标签内容主元素选择器、标签内容列表选择器
+});
+```
+
+具体用法可直接参考上述示例:[给任意元素绑定 tabs 切换功能](#demo-custom)
+
+
+属性
+
+
+{{- d.include("/tabs/detail/options.md") }}
+
+
+新增标签
+
+`tabs.add(id, opts)`
+
+- 参数 `id` : 组件的实例 ID
+- 参数 `opts` : 标签配置项。可选项详见下表
+
+| opts | 描述 | 类型 | 默认值 |
+| --- | --- | --- | --- |
+| title | 标签标题。必填项 | string | - |
+| content | 标签内容。必填项 | string | - |
+| id | 标签的 `lay-id` 属性值 | string | - |
+| index | 活动标签的索引或 `lay-id` 属性值,默认取当前选中标签的索引 | number | - |
+| mode | 标签的插入方式。支持以下可选值:`append` 插入标签到最后 `prepend` 插入标签到最前 `before` 在活动标签前插入 `after` 在活动标签后插入 | string | `append` |
+| active | 是否将新增项设置为活动标签 | boolean | `true` |
+| closable | 标签是否可关闭。初始值取决于 `options.closable` | boolean | `false` |
+| headerItem | 自定义标签头部元素,如 `headerItem: ' '` | string | - |
+| bodyItem | 自定义标签内容元素,如 `bodyItem: '
'` | string | - |
+| done | 标签添加成功后执行的回调函数 | Function | - |
+
+该方法用于给对应的 tabs 实例新增一个标签
+
+```js
+tabs.add('test', {
+ title: 'New Tab 1',
+ content: 'New Tab Content 1',
+ done: function(data) {
+ console.log(data); // 标签相关数据
+
+ // 为新标签头添加任意属性
+ data.headerItem.attr('lay-tips', '111');
+ }
+});
+```
+
+关闭标签
+
+`tabs.close(id, index, force)`
+
+- 参数 `id` : 组件的实例 ID
+- 参数 `index` : 若传入 number 类型,则为标签索引;若传入 string 类型,则为标签的 `lay-id` 属性值
+- 参数 `force` : 是否强制关闭。若设置 `true` 将忽略 `beforeClose` 事件行为。默认 `false`
+
+该方法用于关闭指定的标签项。
+
+```js
+tabs.close('test', 3); // 关闭索引为 3 的标签
+tabs.close('test', 3, true); // 强制关闭索引为 3 的标签
+tabs.close('test', 'abc'); // 关闭 lay-id="abc" 的标签
+```
+
+批量关闭标签
+
+`tabs.closeMult(id, mode, index)`
+
+- 参数 `id` : 组件的实例 ID
+- 参数 `mode` : 关闭方式。支持以下可选值:
+
+| mode | 描述 |
+| --- | --- |
+| other | 关闭除当前标签外的其他标签 |
+| right | 关闭当前标签的右侧所有标签 |
+| all | 关闭所有标签 |
+
+- 参数 `index` : 活动标签的索引或 `lay-id` 属性值,默认取当前选中标签的索引。一般用于标签右键事件。
+
+该方法用于批量关闭标签,若标签项已设置不允许关闭(`lay-closable="false"`),则操作将被忽略。
+
+```js
+tabs.closeMult(id, 'other'); // 关闭除当前活动标签外的其他标签
+tabs.closeMult(id, 'other', 3); // 关闭除索引为 3 的标签外的其他标签
+tabs.closeMult(id, 'other', 'ccc'); // 关闭除 lay-id="ccc" 的标签外的其他标签
+
+tabs.closeMult(id, 'right'); // 关闭当前活动标签的右侧所有标签
+tabs.closeMult(id, 'right', 3); // 关闭索引为 3 的标签的右侧所有标签
+tabs.closeMult(id, 'right', 'ccc'); // 关闭 lay-id="ccc" 的标签的右侧所有标签
+
+tabs.closeMult(id, 'all'); // 关闭所有标签
+```
+
+切换标签
+
+`tabs.change(id, index, force)`
+
+- 参数 `id` : 组件的实例 ID
+- 参数 `index` : 标签索引或标签的 `lay-id` 属性值
+- 参数 `force` : 是否强制切换。若设置 `true` 将忽略 `beforeChange` 事件行为。默认 false
+
+该方法用于切换到指定的标签项。
+
+```js
+tabs.change('test', 3); // 切换到索引为 3 的标签
+tabs.change('test', 3, true); // 强制切换到索引为 3 的标签
+tabs.change('test', 'abc'); // 切换到 lay-id="abc" 的标签
+tabs.change('test', 'abc', true); // 强制切换到 lay-id="abc" 的标签
+```
+
+获取标签相关数据
+
+`tabs.data(id)`
+
+- 参数 `id` : 组件的实例 ID
+
+该方法用于获取标签相关数据。
+
+```js
+var data = tabs.data('test');
+console.log(data);
+```
+
+返回的 `data` 包含以下字段:
+
+```js
+{
+ options, // 标签配置信息
+ container, // 标签容器的相关元素
+ thisHeaderItem, // 当前活动标签头部项
+ thisBodyItem, // 当前活动标签内容项
+ index, // 当前活动标签索引
+ length, // 标签数量
+}
+```
+
+
+
+`tabs.getHeaderItem(id, index)`
+
+- 参数 `id` : 组件的实例 ID
+- 参数 `index` : 若传入 number 类型,则为标签索引;若传入 string 类型,则为标签的 `lay-id` 属性值
+
+该方法用于获取标签头部项元素。
+
+```js
+var headerItem = tabs.getHeaderItem('test', 3); // 获取索引为 3 的标签头部项元素
+var headerItem = tabs.getHeaderItem('test', 'abc'); // 获取 lay-id="abc" 的标签头部项元素
+```
+
+获取标签内容项
+
+`tabs.getBodyItem(id, index)`
+
+- 参数 `id` : 组件的实例 ID
+- 参数 `index` : 若传入 number 类型,则为标签索引;若传入 string 类型,则为标签的 `lay-id` 属性值 2.11.2+
+
+该方法用于获取标签内容项元素。
+
+```js
+var bodyItem = tabs.getBodyItem('test', 3); // 获取索引为 3 的标签内容项元素
+var bodyItem = tabs.getBodyItem('test', 'abc'); // 获取 lay-id="abc" 的标签内容项元素
+```
+
+刷新标签视图
+
+`tabs.refresh(id)`
+
+- 参数 `id` : 组件的实例 ID
+
+该方法用于刷新标签视图,如标签头部的滚动结构等,一般通过非 API 方式对标签进行修改的场景中使用。
+
+```js
+tabs.refresh('test'); // 刷新标签视图
+```
+
+
+事件
+
+`tabs.on('event(id)', callback)`
+
+- 参数介绍详见 `component` 组件的[事件定义](../component/#on)。以下是组件提供的 `event` 事件列表
+
+| event | 描述 |
+| --- | --- |
+| [afterRender](#on-afterRender) | 标签渲染后的事件 |
+| [beforeChange](#on-beforeChange) | 标签切换前的事件 |
+| [afterChange](#on-afterChange) | 标签切换后的事件 |
+| [beforeClose](#on-beforeClose) | 标签关闭前的事件 |
+| [afterClose](#on-afterClose) | 标签关闭后的事件 |
+
+
+标签渲染后的事件
+
+`tabs.on('afterRender(id)', callback)`
+
+标签渲染成功后触发。
+
+```js
+tabs.on('afterRender(testID)', function(data){
+ console.log(data); // 标签相关数据
+});
+```
+
+标签切换前的事件
+
+`tabs.on('beforeChange(id)', callback)`
+
+标签在切换前触发,通过在事件中 `return false` 可阻止默认标签切换行为。通常和 `tabs.change()` 方法搭配使用。
+
+```js
+// tabs 切换前的事件
+tabs.on(`beforeChange(testID)`, function(data) {
+ console.log(data); // 标签相关数据
+ console.log(data.from.index); // 切换前的选中标签索引
+ console.log(data.from.headerItem); // 切换前的选中标签头部项
+ console.log(data.to.index); // 切换后的选中标签索引
+ console.log(data.to.headerItem); // 切换后的选中标签头部项
+
+ // 阻止标签默认关闭
+ return false;
+});
+```
+
+示例演示:
+
+
+
+{{- d.include("/tabs/examples/beforeChange.md") }}
+
+
+
+标签切换后的事件
+
+`tabs.on('afterChange(id)', callback)`
+
+标签成功切换后触发。
+
+```js
+// tabs 切换后的事件
+tabs.on('afterChange(testID)', function(data) {
+ console.log(data);
+});
+```
+
+标签关闭前的事件
+
+`tabs.on('beforeClose(id)', callback)`
+
+标签在切换前触发,通过在事件中 `return false` 可阻止默认标签切换行为。通常和 `tabs.close()` 方法搭配使用。
+
+
+
+{{- d.include("/tabs/examples/beforeClose.md") }}
+
+
+
+标签关闭后的事件
+
+`tabs.on('afterClose(id)', callback)`
+
+标签被成功关闭后触发。
+
+```js
+// tabs 关闭后的事件
+tabs.on('afterClose(testID)', function(data) {
+ console.log(data);
+});
+```
+
+## 💖 心语
+
+tabs 是通过 component 重构的首个组件,它来自于最早试图发布的 Layui 3.0(后因为 3.0 技术路线的变化,而整理放至 2.10+ 版本中),目的是将 element 模块中的 tab 组件进行解耦,增强其可扩展性。为了给开发者必要的时间缓冲,我们会将旧 tab 组件仍然保留在后续的若干版本中,但会在合适的时机对旧 tab 组件进行剔除,建议开发者尽量提前过渡到当前新的 tabs 组件。
+
+
diff --git a/docs/timeline/index.md b/docs/timeline/index.md
new file mode 100644
index 000000000..7807d8c11
--- /dev/null
+++ b/docs/timeline/index.md
@@ -0,0 +1,99 @@
+---
+title: 时间线 timeline
+toc: true
+---
+
+# 时间线
+
+> 时间线 `timeline` 用于将时间抽象到二维平面,垂直呈现一段从过去到现在的故事。
+
+常规时间线
+
+
+
+
+
+
+
+
8月18日
+
+ 多年前,Layui 2.0 的发布前夜,记录着这样的一段心理活动。
+ 这是一个怎样的版本?它将受众如何?
+ 又是谁在指引着我去创作,是基于成就感的驱动,还是试图建立我与客观世界的某种沟通
+
+
+
+
+
+
+
8月16日
+
Layui 使用率最高的组件有
+
+
+
+
+
+
+
8月15日
+
+ 这片广袤的土地孕育了璀璨的华夏文化,和我们这个饱受沧桑的民族。
+ 勤劳、淳朴、善良而又充满智慧的国人,一代又一代人的艰苦奋斗,古老的文明重新焕发出光彩。
+
+
+
+
+
+
+
+
+时间线上的图标可任意定义,右侧内容区域可自由填充。
+
+简约时间线
+
+
+
+
+
+
+
+
2023年,Layui 情怀版本 2.8.0 发布,新官网上线,且文档全部重写并开源。
+
+
+
+
+
+
2021年,Layui 原官网下线,此后 Layui 进入两年的低谷期。
+
+
+
+
+
+
2017年,Layui 里程碑版本 2.0.0 发布,此后 Layui 进入三年的高光期。
+
+
+
+
+
+
+
+
+透过这示例,见证 Layui 的起起伏伏。
diff --git a/docs/transfer/detail/demo.md b/docs/transfer/detail/demo.md
new file mode 100644
index 000000000..68f52d848
--- /dev/null
+++ b/docs/transfer/detail/demo.md
@@ -0,0 +1,276 @@
+
+
+
+
+
+
+
+
+
+定义标题及数据源
+
+
+
+
+
+
+
+
+
+
+初始右侧数据
+
+
+
+
+
+
+
+
+
+
+显示搜索框
+
+
+
+
+
+
+
+
+
+
+数据格式解析
+
+
+
+
+
+
+
+
+
+
+穿梭时的回调
+
+
+
+
+
+
+
+
+
+
+实例调用
+
+
+
+
+ 获取右侧数据
+ 重载实例
+
+
+
+
+
+
+
diff --git a/docs/transfer/detail/options.data.md b/docs/transfer/detail/options.data.md
new file mode 100644
index 000000000..eb0caae92
--- /dev/null
+++ b/docs/transfer/detail/options.data.md
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+ 属性名
+ 描述
+ 类型
+ 默认值
+
+
+
+
+title
+
+
+数据标题
+
+
+string
+-
+
+
+value
+
+
+数据值
+
+
+string
+-
+
+
+checked
+
+
+是否选中状态
+
+
+boolean
+
+
+`false`
+
+
+
+
+disabled
+
+
+是否禁用状态
+
+
+boolean
+
+
+`false`
+
+
+
+
+
diff --git a/docs/transfer/detail/options.md b/docs/transfer/detail/options.md
new file mode 100644
index 000000000..7baf277e4
--- /dev/null
+++ b/docs/transfer/detail/options.md
@@ -0,0 +1,226 @@
+
+
+
+
+
+
+
+
+
+ 属性名
+ 描述
+ 类型
+ 默认值
+
+
+
+
+elem
+
+
+绑定元素选择器或 DOM 对象
+
+
+string/DOM
+-
+
+
+title
+
+
+穿梭框左右面板头部标题
+
+
+array
+
+
+查看默认值
+
+
+
+
+data
+
+
+穿梭框的数据源。格式详见:[#data 格式](#options.data)
+
+
+array
+-
+
+
+value
+
+
+初始选中的数据(右侧列表)
+
+
+array
+-
+
+
+id
+
+
+设置实例唯一索引,用于其他方法传参使用。
+
+
+string
+-
+
+
+showSearch
+
+
+是否开启搜索。支持以下可选值:
+
+- `false` 不开启搜索(默认)
+- `true` 开启搜索,且匹配时不区分大小写
+- `cs` 开启搜索,且匹配时区分大小写 2.7+
+
+
+boolean string
+
+
+`false`
+
+
+
+
+width
+
+
+定义左右穿梭框宽度
+
+
+number
+
+
+`200`
+
+
+
+
+height
+
+
+定义左右穿梭框高度
+
+
+number
+
+
+`360`
+
+
+
+
+text
+
+
+自定义默认文本, `object` 类型。支持以下属性:
+
+```
+text: {
+ none: '无数据', // 没有数据时的文案
+ searchNone: '无匹配数据' // 搜索无匹配数据时的文案
+}
+```
+
+
+
+
+
+
+
+
+
+[回调函数](#options.callback)
+
+
+
+
+
+
+onchange
+
+
+左右穿梭时的回调函数。返回的参数如下:
+
+```
+onchange: function(data, index){
+ console.log(data); // 得到当前被穿梭的数据
+ console.log(index); // 如果数据来自左边,index 为 0,否则为 1
+}
+```
+
+
+boolean
+
+
+`false`
+
+
+
+
+dblclick 2.9.3+
+
+
+双击时的回调函数。返回的参数如下:
+
+```
+dblclick: function(obj){
+ console.log(obj.elem); // 点击的元素
+ console.log(obj.data); // 得到点击项的数据
+ console.log(obj.index); // 如果数据来自左边,index 为 0,否则为 1
+
+ return false // 返回 false 会阻止穿梭
+}
+```
+
+
+function
+
+
+ `null`
+
+
+
+
+
+
+[parseData](#options.parseData)
+
+
+
+
+
+数据格式解析的回调函数,用于将返回的任意数据格式解析成 transfer 组件规定的
data 格式
+
+
+```
+transfer.render({
+ elem: '',
+ data: [ // 任意数据
+ {"id": "1", "name": "李白"},
+ {"id": "2", "name": "杜甫"},
+ {"id": "3", "name": "贤心"}
+ ],
+ parseData: function(res){ // 解析成规定的 data 格式
+ return {
+ "value": res.id, // 数据值
+ "title": res.name, // 数据标题
+ "disabled": res.disabled, // 是否禁用
+ "checked": res.checked // 是否选中
+ };
+ }
+});
+```
+
+
+
+
+
diff --git a/docs/transfer/index.md b/docs/transfer/index.md
new file mode 100644
index 000000000..21fad1e89
--- /dev/null
+++ b/docs/transfer/index.md
@@ -0,0 +1,85 @@
+---
+title: 穿梭框组件 transfer
+toc: true
+---
+
+# 穿梭框组件
+
+> 穿梭框组件 `transfer` 以左右栏 `checkbox` 列表为表现形式,可对列表进行选择并移动到另一栏。
+
+示例
+
+
+{{- d.include("/transfer/detail/demo.md") }}
+
+
+API
+
+| API | 描述 |
+| --- | --- |
+| var transfer = layui.transfer | 获得 `transfer` 模块。 |
+| [基础接口](../component/#export) 2.13+ | 该组件由 `component` 构建,因此继承其提供的基础接口。|
+| [transfer.render(options)](#render) | transfer 组件渲染,核心方法。 |
+| [transfer.reload(id, options)](#reload) | 重载实例 |
+| [transfer.getData(id)](#getData) | 获得右侧数据 |
+
+渲染
+
+`transfer.render(options);`
+
+- 参数 `options` : 基础属性选项。[#详见属性](#options)
+
+属性
+
+
+{{- d.include("/transfer/detail/options.md") }}
+
+
+data 格式
+
+
+{{- d.include("/transfer/detail/options.data.md") }}
+
+
+重载
+
+`transfer.reload(id, options);`
+
+- 参数 `id` : 对应渲染时定义的 `id` 属性值
+- 参数 `options` : 基础属性选项。[#详见属性](#options)
+
+```
+var transfer = layui.transfer;
+
+// 渲染
+transfer.render({
+ elem: '', // 绑定元素选择器
+ id: 'test', // 自定义 id 索引
+ // 其他属性 …
+});
+// 重载
+transfer.reload('test', { // options
+ title: ['title 1', 'title 2']
+});
+```
+
+获得右侧数据
+
+`transfer.getData(id);`
+
+- 参数 `id` : 对应渲染时定义的 `id` 属性值
+
+穿梭框的右侧数据通常被认为是选中数据,因此你需要得到它,并进行提交等操作。
+
+```
+var transfer = layui.transfer;
+
+// 渲染
+transfer.render({
+ elem: '', // 绑定元素选择器
+ id: 'test', // 自定义 id 索引
+ // 其他属性 …
+});
+// 获得右侧数据
+var getData = transfer.getData('test');
+```
diff --git a/docs/tree/detail/demo.md b/docs/tree/detail/demo.md
new file mode 100644
index 000000000..dd71e96d1
--- /dev/null
+++ b/docs/tree/detail/demo.md
@@ -0,0 +1,179 @@
+综合演示
+
+
+
+
+
+ 获取选中节点数据
+ 勾选指定节点
+ 重载实例
+
+
+
+
+
+
+
+
+
+无连接线风格
+
+
+
+
+
+
+
+
+
+
+仅图标控制伸缩
+
+
+
+
+
+
+
+
+
+
+手风琴模式
+
+
+
+
+
+
+
+
+
+
+开启复选框
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/tree/detail/options.data.md b/docs/tree/detail/options.data.md
new file mode 100644
index 000000000..202df1462
--- /dev/null
+++ b/docs/tree/detail/options.data.md
@@ -0,0 +1,110 @@
+
+
+
+
+
+
+
+
+
+ 属性名
+ 描述
+ 类型
+ 默认值
+
+
+
+
+title
+
+
+节点标题
+
+
+string
+-
+
+
+id
+
+
+节点唯一索引值,用于对指定节点进行各类操作
+
+
+string
+-
+
+
+field
+
+
+节点字段名
+
+
+string
+-
+
+
+children
+
+
+子节点。支持设定属性选项同父节点
+
+
+array
+-
+
+
+href
+
+
+点击节点弹出新窗口对应的 url。需开启 isJump 基础属性才有效。
+
+
+string
+-
+
+
+spread
+
+
+节点是否初始展开
+
+
+boolean
+
+
+`false`
+
+
+
+
+checked
+
+
+节点是否初始为选中状态。需开启 `showCheckbox` 基础属性时有效。
+
+
+boolean
+
+
+`false`
+
+
+
+
+disabled
+
+
+节点是否为禁用状态
+
+
+boolean
+
+
+`false`
+
+
+
+
+
diff --git a/docs/tree/detail/options.md b/docs/tree/detail/options.md
new file mode 100644
index 000000000..744d45f32
--- /dev/null
+++ b/docs/tree/detail/options.md
@@ -0,0 +1,246 @@
+
+
+
+
+
+
+
+
+
+ 属性名
+ 描述
+ 类型
+ 默认值
+
+
+
+
+elem
+
+
+绑定元素选择器
+
+
+string/DOM
+-
+
+
+data
+
+
+`tree` 的数据源。其格式详见:[#data 格式](#options.data)
+
+
+array
+-
+
+
+id
+
+
+设置实例唯一索引,用于其他方法传参使用。
+
+
+string
+-
+
+
+showCheckbox
+
+
+是否显示复选框
+
+
+boolean
+
+
+`false`
+
+
+
+
+edit
+
+
+是否开启节点的右侧操作图标。支持以下可选值:
+
+- 若为 `true`,则默认显示「改删」图标
+- 若为 数组,则可自由配置操作图标,如:`edit:['add', 'update', 'del']` ,且图标将按照数组的顺序显示。
+
+
+boolean array
+
+
+`false`
+
+
+
+
+accordion
+
+
+是否开启手风琴模式
+
+
+boolean
+
+
+`false`
+
+
+
+
+onlyIconControl
+
+
+是否仅允许节点左侧图标控制展开伸缩。
+
+- 默认为 `false`,即点击节点本身也可控制伸缩
+- 若值为 `true`,则只能通过节点左侧图标来展开收缩
+
+
+boolean
+
+
+`false`
+
+
+
+
+isJump
+
+
+是否允许点击节点时弹出新窗口跳转。若为 `true`,则需在对应的 data 中设定 href 属性(url 格式)
+
+
+boolean
+
+
+`false`
+
+
+
+
+showLine
+
+
+是否开启节点连接线。若设为 `false`,则节点左侧出现三角图标。
+
+
+boolean
+
+
+`true`
+
+
+
+
+
+
+[customName](#options.customName) 2.8.14+
+
+
+
+
+自定义 `data` 数据源中常用的字段名称。
+
+
+object
+-
+
+
+text
+
+
+自定义默认文本,`object` 类型。支持以下属性:
+
+```
+text: {
+ defaultNodeName: '未命名', // 节点默认名称
+ none: '无数据' // 数据为空时的提示文本
+}
+```
+
+
+
+
+
+
+
+
+
+[回调函数](#options.callback)
+
+
+
+
+
+
+click
+
+
+
+ 节点被点击的回调函数。返回的参数如下:
+
+
+```
+click: function(obj){
+ console.log(obj.data); // 得到当前点击的节点数据
+ console.log(obj.state); // 得到当前节点的展开状态:open、close、normal
+ console.log(obj.elem); // 得到当前节点元素
+
+ console.log(obj.data.children); // 当前节点下是否有子节点
+}
+```
+
+
+
+
+oncheck
+
+
+
+ 点击复选框时的回调函数,返回的参数如下:
+
+
+```
+oncheck: function(obj){
+ console.log(obj.data); // 得到当前点击的节点数据
+ console.log(obj.checked); // 节点是否被选中
+ console.log(obj.elem); // 得到当前节点元素
+}
+```
+
+
+
+
+operate
+
+
+
+ 点击节点的右侧操作图标的回调函数,返回的参数如下:
+
+
+```
+operate: function(obj){
+ var type = obj.type; // 得到操作类型:add、edit、del
+ var data = obj.data; // 得到当前节点的数据
+ var elem = obj.elem; // 得到当前节点元素
+
+ // Ajax 操作
+ var id = data.id; // 得到节点索引
+ if(type === 'add'){ // 增加节点
+ //返回 key 值
+ return 123;
+ } else if(type === 'update'){ // 修改节点
+ console.log(elem.find('.lay-tree-txt').html()); // 得到修改后的内容
+ } else if(type === 'del'){ // 删除节点
+ // …
+ };
+}
+```
+
+
+
+
+
diff --git a/docs/tree/index.md b/docs/tree/index.md
new file mode 100644
index 000000000..67ab9731b
--- /dev/null
+++ b/docs/tree/index.md
@@ -0,0 +1,129 @@
+---
+title: 树组件 tree
+toc: true
+---
+
+# 树组件
+
+> 树组件 `tree` 是以树形为结构的菜单伸缩型组件,*当前版本中,`tree`主要用于树菜单展示,交互性相对较弱。*
+
+示例
+
+
+{{- d.include("/tree/detail/demo.md") }}
+
+
+API
+
+| API | 描述 |
+| --- | --- |
+| var tree = layui.tree | 获得 `tree` 模块。 |
+| [基础接口](../component/#export) 2.13+ | 该组件由 `component` 构建,因此继承其提供的基础接口。|
+| [tree.render(options)](#render) | tree 组件渲染,核心方法。 |
+| [tree.getChecked(id)](#getChecked) | 获取选中的节点数据 |
+| [tree.setChecked(id, idArr)](#setChecked) | 设置对应 id 的节点选中 |
+| [tree.reload(id, options)](#reload) | tree 实例重载 |
+
+渲染
+
+`tree.render(options);`
+
+- 参数 `options` : 基础属性选项。[#详见属性](#options)
+
+属性
+
+
+{{- d.include("/tree/detail/options.md") }}
+
+
+data 格式
+
+
+{{- d.include("/tree/detail/options.data.md") }}
+
+
+
+
+您可以对上述 `data` 中常用的字段进行自定义名称 2.8.14+ :
+
+
+
+```
+var tree = layui.tree;
+// 渲染
+tree.render({
+ elem: '', // 绑定元素选择器
+ id: 'test', // 自定义 id 索引
+ data: [], // 数据源
+ customName: { // 自定义 data 字段名 --- 2.8.14+
+ id: 'id',
+ title: 'title',
+ children: 'children'
+ },
+ // 其他属性 …
+});
+```
+
+获取选中的节点数据
+
+`tree.getChecked(id);`
+
+- 参数 `id` : 对应 tree 渲染时定义的 id 属性值
+
+```
+var tree = layui.tree;
+
+// 渲染
+tree.render({
+ elem: '', // 绑定元素选择器
+ id: 'test', // 自定义 id 索引
+ // 其他属性 …
+});
+
+// 获取选中的节点数据
+var checkData = tree.getChecked('test');
+```
+
+设置对应 id 的节点选中
+
+`tree.setChecked(id, idArr);`
+
+- 参数 `id` : 对应 tree 渲染时定义的 id 属性值
+- 参数 `idArr` : 对应 tree 渲染时的 data 中的 id 属性值。数组格式,可设置多个。
+
+```
+var tree = layui.tree;
+
+// 渲染
+tree.render({
+ elem: '', // 绑定元素选择器
+ id: 'test', // 自定义 id 索引
+ // 其他属性 …
+});
+
+// 设置对应 id 的节点选中
+tree.setChecked('test', [1, 3]); // 批量勾选 id 为 1,3 的节点
+```
+
+重载
+
+`tree.reload(id, idArr);`
+
+- 参数 `id` : 对应 tree 渲染时定义的 id 属性值
+- 参数 `options` : 基础属性选项。[#详见属性](#options)
+
+```
+var tree = layui.tree;
+
+// 渲染
+tree.render({
+ elem: '', // 绑定元素选择器
+ id: 'test', // 自定义 id 索引
+ // 其他属性 …
+});
+
+// 重载
+tree.reload('test', { // options
+ data: []
+});
+```
diff --git a/docs/treeTable/detail/demo.md b/docs/treeTable/detail/demo.md
new file mode 100644
index 000000000..790f817e0
--- /dev/null
+++ b/docs/treeTable/detail/demo.md
@@ -0,0 +1,18 @@
+综合演示
+
+
+
+{{- d.include("/treeTable/examples/demo.md") }}
+
+
+
+
+
+
+
diff --git a/docs/treeTable/detail/options.md b/docs/treeTable/detail/options.md
new file mode 100644
index 000000000..bcf11f8c9
--- /dev/null
+++ b/docs/treeTable/detail/options.md
@@ -0,0 +1,184 @@
+
+
+
+
+
+
+
+ 属性名
+ 描述
+
+
+
+
+tree
+
+
+treeTable 组件的特定属性集,包含以下「子成员集」:
+
+| 属性 | 描述 |
+| --- | --- |
+| [customName](#options.tree.customName) | 自定义属性名的集合 |
+| [view](#options.tree.view) | 视图相关的属性集合 |
+| [data](#options.tree.data) | 数据相关的属性集合 |
+| [async](#options.tree.async) | 异步相关的属性集合 |
+| [callback](#options.tree.callback) | 事件回调相关的属性集合 |
+
+用法如下:
+
+```js
+treeTable.render({
+ elem: '',
+ tree: { // treeTable 特定属性集
+ customName: {},
+ data: {},
+ view: {},
+ async: {},
+ callback: {}
+ },
+ // 其他 table 属性
+});
+````
+
+
+
+
+tree.customName
+
+
+
+
+自定义属性名的集合,包含以下成员:
+
+
+
+| 属性 | 描述 | 类型 | 默认值 |
+| --- | --- | --- | --- |
+| children | 自定义「子节点集合」的属性名 | string | `children` |
+| isParent | 自定义「是否属于父节点」的属性名 | string | `isParent` |
+| name | 自定义「节点」属性名 | string | `name` |
+| id | 自定义「节点索引」属性名 | string | `id` |
+| pid | 自定义「父节点索引」属性名 | string | `parentId` |
+| icon | 自定义图标的属性名称 | string | `icon` |
+
+
+
+
+tree.view
+
+
+
+
+视图相关的属性集合,包含以下成员:
+
+
+
+| 属性 | 描述 | 类型 | 默认值 |
+| --- | --- | --- | --- |
+| indent | 层级缩进量 | number | `14` |
+| flexIconClose | 自定义关闭时的折叠按钮图标 | string | - |
+| flexIconOpen | 自定义打开时的折叠按钮图标 | string | - |
+| showIcon | 是否显示节点图标 | boolean | `true` |
+| icon | 自定义节点图标。若设置了该属性或数据中有该字段信息,不管打开还是关闭都以这个图标的值为准 | string | - |
+| iconClose | 自定义关闭时的节点图标 | string | - |
+| iconOpen | 自定义打开时的节点图标 | string | - |
+| iconLeaf | 自定义叶子节点的图标 | string | - |
+| showFlexIconIfNotParent | 若非父节点时,是否显示折叠图标 | boolean | `false` |
+| dblClickExpand | 双击节点时,是否自动展开父节点 | boolean | `true` |
+| expandAllDefault 2.8.7+ | 是否默认展开全部节点 | boolean | `false` |
+
+自定义图标支持 HTML 字符串和图标类名。例如:
+
+- `' '`
+- `'lay-icon lay-icon-addition'`
+
+
+
+
+tree.data
+
+
+
+
+数据相关的属性集合,包含以下成员:
+
+
+
+| 属性 | 描述 | 类型 | 默认值 |
+| --- | --- | --- | --- |
+| isSimpleData | 是否使用平铺数据格式(Array) | boolean | `false` |
+| rootPid | 用于设置根节点的 `pid` 属性值 | string | `null` |
+| cascade | 用于设置复选的级联方式。支持以下可选值:all : 所有节点联动parent : 仅对父节点联动children : 仅对子节点联动none 2.8.16+ : 不做任何联动 | string | `all` |
+
+
+
+
+tree.async
+
+
+
+
+异步相关的属性集合,包含以下成员:
+
+
+
+| 属性 | 描述 | 类型 | 默认值 |
+| --- | --- | --- | --- |
+| enable | 是否开启异步加载模式。只有开启时 `async` 的其他属性选项才有效。 **注意:** 异步加载子节点不应跟 `simpleData` 同时开启,可以是 `url+simpleData` 的方式,获取完整的简单数据进行转换。若开启异步加载模式,即表示按需异步加载子节点。 | boolean | `false` |
+| url | 异步加载的接口,可以根据需要设置与顶层接口不同的接口,若相同可不设置该属性 | string | - |
+| [format](#options.tree.async.format) | 用于处理异步子节点数据的回调函数,该属性优先级高于 `async.url` 属性。用法详见下文。 | function | - |
+| type | 请求的接口类型,设置可缺省同上 | string | - |
+| contentType | 提交参数的数据类型,设置可缺省同上 | string | - |
+| headers | 提交请求头,设置可缺省同上 | object | - |
+| where | 提交参数的数据,设置可缺省同上 | object | - |
+| autoParam | 自动参数,可以根据配置项以及当前节点的数据传参,如: `['type', 'age=age', 'parentId=id']` ,那么其请求参数将包含: `{type: '父节点 type', age: '父节点 age', parentId: '父节点 id'}` | array | - |
+
+
+
+**format 示例** :
+
+
+
+```
+treeTable.render({
+ elem: '',
+ tree: {
+ enable: true,
+ async: {
+ format: function(trData, options, callback){
+ // trData 为行数据、options 为 treeTable 属性选项
+ // callbacck 为子节点的渲染函数
+ // 可利用该函数对子节点数据进行异步请求或其他格式化处理
+ var nodeList = [
+ {id: 111, name: '子节点1'},
+ {id: 333, name: '子节点3'}
+ ];
+ callback(nodeList);
+ }
+ }
+ }
+})
+```
+
+
+
+
+tree.callback
+
+
+
+
+事件回调相关的属性集合,包含以下成员:
+
+
+
+| 属性 | 描述 |
+| --- | --- |
+| beforeExpand | 展开前回调函数。可以在展开或者关闭之前调用,传入当前表格 `id` ,当前操作的行数据以及要展开或关闭的状态,若回调返回 `false` 则取消该次操作。 返回的参数包含: `function(tableId, trData, expandFlag){ console.log(arguments); }` |
+| onExpand | 展开或关闭后的回调函数,返回参数同 `beforeExpand` |
+
+
+
+
+
+
diff --git a/docs/treeTable/examples/demo.md b/docs/treeTable/examples/demo.md
new file mode 100644
index 000000000..e710b128b
--- /dev/null
+++ b/docs/treeTable/examples/demo.md
@@ -0,0 +1,121 @@
+
+
+
+
+
+
+
+
+
diff --git a/docs/treeTable/index.md b/docs/treeTable/index.md
new file mode 100644
index 000000000..a6b89ac4f
--- /dev/null
+++ b/docs/treeTable/index.md
@@ -0,0 +1,387 @@
+---
+title: 树表组件 treeTable
+toc: true
+---
+
+# 树表组件 2.8+
+
+> 树表组件 `treeTable` 是基于 `table` 组件延伸的树形表格组件,支持常见的树组件功能。
+> 注意:*该组件不支持 IE8,若要支持,可自行添加 polyfill 实现兼容。*
+
+示例
+
+以下所有示例中演示的数据均为「静态模拟数据」,实际使用时换成您的真实接口即可。
+
+
+{{- d.include("/treeTable/detail/demo.md") }}
+
+
+
+
+API
+
+`table` 组件的所有 `API` 均适用于 `treeTable` 组件。在此基础上,`treeTable` 还专门提供了以下方法:
+
+| API | 描述 |
+| --- | --- |
+| var treeTable = layui.treeTable; | 获得 `treeTable` 模块。 |
+| [treeTable.render(options)](#render) | treeTable 组件渲染,核心方法。 |
+| [treeTable.reload(id, options)](#reload) | 树表完整重载。 |
+| [treeTable.reloadData(id, options)](#reload) | 树表数据重载。 |
+| [treeTable.reloadAsyncNode(id, index)](#reloadAsyncNode) | 重载异步子节点 |
+| [treeTable.getData(id, isSimpleData)](#getData) | 获取树表数据。 |
+| [treeTable.getNodeById(id, dataId)](#getNodeById) | 获取节点信息集 |
+| [treeTable.getNodesByFilter(id, filter, opts)](#getNodesByFilter) | 获取符合过滤规则的节点信息集 |
+| [treeTable.getNodeDataByIndex(id, index)](#getNodeDataByIndex) | 通过行元素对应的 `data-index` 属性获取对应行数据。 |
+| [treeTable.updateNode(id, index, data)](#updateNode) | 更新行数据。 |
+| [treeTable.removeNode(id, index)](#removeNode) | 删除行记录。 |
+| [treeTable.addNodes(id, opts)](#addNodes) | 新增行记录。 |
+| [treeTable.expandNode(id, opts)](#expandNode) | 展开或关闭节点。 |
+| [treeTable.expandAll(id, expandFlag)](#expandAll) | 展开或关闭全部节点。 |
+| [treeTable.setRowChecked(id, opts)](#setRowChecked) | 设置行选中状态 |
+| [treeTable.checkAllNodes(id, checked)](#checkAllNodes) | 全选或取消全选 |
+| [treeTable.checkStatus(id, includeHalfCheck)](#checkStatus) | 获取选中行相关数据 |
+| [treeTable.on(\'event(filter)\', callback)](#on) | treeTable 相关事件 |
+
+渲染
+
+`treeTable.render(options);`
+
+- 参数 `options` : 基础属性选项。[#详见属性](#options)
+
+该组件渲染的使用方式与 `table` 组件完全相同。
+
+属性
+
+`table` 组件的所有基础属性均适用于 `treeTable` 组件。在此基础上,`treeTable` 还专门提供了 `tree` 属性集:
+
+
+{{- d.include("/treeTable/detail/options.md") }}
+
+
+重载
+
+即对一段已经渲染好的表格重新设置属性并渲染,可分为以下几种重载方式:
+
+| 重载方式 | API |
+| --- | --- |
+| 完整重载 | treeTable.reload(id, options) |
+| 仅数据重载 | treeTable.reloadData(id, options) |
+
+- 参数 `id` : treeTable 渲染时的 id 属性值
+- 参数 `options` : 基础属性选项。[#详见属性](#options)
+
+使用方式与 `table` 组件完全相同,具体用法可参考:[table 重载](../table/#reload)
+
+
+重载异步子节点
+
+`treeTable.reloadAsyncNode(id, index)`
+
+- 参数 `id` : treeTable 渲染时的 id 属性值
+- 参数 `index` : 节点对应的行下标,一般可通过 ` ` 元素的 `data-index` 属性获得
+
+该方法用于在异步模式下,对节点进行重载。
+
+```js
+// 渲染
+treeTable.render({
+ elem: '', // 绑定元素选择器
+ id: 'test', // 自定义 id 索引
+ async: {
+ enable: true // 开启异步加载模式
+ }
+ // 其他属性 …
+});
+// 重载子节点
+treeTable.reloadAsyncNode('test', 0); // 第一行
+```
+
+
+获取树表数据
+
+`treeTable.getData(id, isSimpleData);`
+
+- 参数 `id` : treeTable 渲染时的 id 属性值
+- 参数 `isSimpleData` : 是否为简单数据,为 `true` 时返回简单数据结构的数据,否则则为带层级的数据
+
+该方法用于获取表格当前页的全部数据,它对应的是接口返回的原始数据,不包含 `treeTable` 组件内部的特定字段。
+
+```js
+// 渲染
+treeTable.render({
+ elem: '', // 绑定元素选择器
+ id: 'test', // 自定义 id 索引
+ // 其他属性 …
+});
+// 获取当前页接口的树表数据
+var data = treeTable.getData('test'); // 获取第一行的数据
+console.log(data);
+```
+
+获取节点信息集
+
+`treeTable.getNodeById(id, dataId)`
+
+- 参数 `id` : treeTable 渲染时的 `id` 属性值
+- 参数 `dataId` : 数据项的 `id` 属性值
+
+```js
+// 渲染
+treeTable.render({
+ elem: '', // 绑定元素选择器
+ id: 'test', // 自定义 id 索引
+ // 其他属性 …
+});
+// 获取节点信息集
+var obj = treeTable.getNodeById('test', 1);
+console.log(obj);
+```
+
+获取符合过滤规则的节点信息集
+
+`treeTable.getNodesByFilter(id, filter, opts)`
+
+- 参数 `id` : treeTable 渲染时的 `id` 属性值
+- 参数 `filter` : 过滤函数
+- 参数 `opts` : 该方法的属性选项,详见下表:
+
+| 属性名 | 描述 | 类型 | 默认值 |
+| --- | --- | --- | --- |
+| isSingle | 是否只找到第一个 | boolean | `false` |
+| parentNode | 在指定在某个父节点下的子节点中搜索 | object | - |
+
+```js
+// 渲染
+treeTable.render({
+ elem: '', // 绑定元素选择器
+ id: 'test', // 自定义 id 索引
+ // 其他属性 …
+});
+// 获取节点信息集
+var obj = treeTable.getNodesByFilter('test', function(item){
+ // 自定义过滤条件
+ return item.id > 1000;
+});
+console.log(obj);
+```
+
+
+获取树表对应下标的数据
+
+`treeTable.getNodeDataByIndex(id, index);`
+
+- 参数 `id` : treeTable 渲染时的 `id` 属性值
+- 参数 `index` : 节点对应的行下标,一般可通过 ` ` 元素的 `data-index` 属性获得
+
+该方法用于获取表格当前页对应下表的数据,返回的数据格式同 `treeTable.getData()` 方法。
+
+```js
+// 渲染
+treeTable.render({
+ elem: '', // 绑定元素选择器
+ id: 'test', // 自定义 id 索引
+ // 其他属性 …
+});
+// 获取树表对应下标的数据
+var obj = treeTable.getNodeDataByIndex('test', 0); // 获取第一行的数据
+console.log(obj);
+```
+
+更新行数据
+
+`treeTable.updateNode(id, index, data);`
+
+- 参数 `id` : treeTable 渲染时的 id 属性值
+- 参数 `index` : 节点对应的行下标,一般可通过 ` ` 元素的 `data-index` 属性获得
+- 参数 `data` : 更新的数据项,可包含要更新的各种字段
+
+```js
+// 渲染
+treeTable.render({
+ elem: '', // 绑定元素选择器
+ id: 'test', // 自定义 id 索引
+ // 其他属性 …
+});
+// 更新行数据
+var data = treeTable.updateNode('test', 0, { // 更新第一行的数据
+ title: '123'
+});
+```
+
+删除行记录
+
+`treeTable.removeNode(id, index);`
+
+- 参数 `id` : treeTable 渲染时的 `id` 属性值
+- 参数 `index/node` : 要删除的节点数据,也可以是节点对应的行下标( `data-index`)
+
+```js
+// 渲染
+treeTable.render({
+ elem: '', // 绑定元素选择器
+ id: 'test', // 自定义 id 索引
+ // 其他属性 …
+});
+// 删除行记录
+treeTable.removeNode('test', 0); // 删除第一行
+```
+
+
+新增行数据
+
+`treeTable.addNodes(id, opts);`
+
+- 参数 `id` : treeTable 渲染时的 `id` 属性值
+- 参数 `opts` : 该方法可支持的可选属性项,详见下表:
+
+| opts | 描述 | 类型 | 默认值 |
+| --- | --- | -- | --- |
+| parentIndex | 父节点数据下标 | number | - |
+| index | 节点对应的行下标。若为 `-1` 表示插入到最后,否则则插入到对应下标。 | number | `-1`|
+| data | 新增的节点数据项。若新增的是多个节点,则用数组的形式。若只有一个节点可以是普通对象形式 | object | - |
+| focus | 是否聚焦到新增的节点。若存在多个,则聚焦到第一个新增的节点 | boolean | `false` |
+
+该方法可返回新增后的数据项。详细用法可参考:[#示例](#examples)
+
+```js
+// 渲染
+treeTable.render({
+ elem: '', // 绑定元素选择器
+ id: 'test', // 自定义 id 索引
+ // 其他属性 …
+});
+// 新增行数据
+treeTable.addNodes('test', {
+ parentIndex: 0, // 一般在 tool 事件中,可通过对应数据项中的 `LAY_DATA_INDEX` 特定属性获得
+ index: 1,
+ data: {
+ title: '新节点-1'
+ }
+});
+```
+
+
+展开或关闭节点
+
+`treeTable.expandNode(id, opts);`
+
+- 参数 `id` : treeTable 渲染时的 `id` 属性值
+- 参数 `opts` : 该方法可支持的可选属性项,详见下表:
+
+| opts | 描述 | 类型 | 默认值 |
+| --- | --- | -- | --- |
+| index | 节点对应的行下标,一般可通过 ` ` 元素的 `data-index` 属性获得 | number | - |
+| expandFlag | 设置展开或关闭状态,若为 `true` 则表示展开;`false` 则为关闭;`null` 则表示切换 | boolean/null | - |
+| inherit | 子节点是否继承父节点的展开或关闭状态,`expandFlag` 属性必须为 `boolean` 型时才有效。 | boolean | `false` |
+| callbackFlag | 是否触发 tree.callback 事件(`beforeExpand,onExpand`) | boolean | `false` |
+| done 2.11.3+ | 节点操作完成后的回调函数 | (tableId, trData, trExpand) => void | - |
+
+若操作的节点不是一个父节点,则返回 `null`,否则返回操作之后的折叠状态。
+
+```js
+// 渲染
+treeTable.render({
+ elem: '', // 绑定元素选择器
+ id: 'test', // 自定义 id 索引
+ // 其他属性 …
+});
+// 展开或关闭对应节点
+treeTable.expandNode('test', {
+ index: 0, // 第一行
+ expandFlag: true // 展开
+});
+```
+
+展开或关闭全部节点
+
+`treeTable.expandAll(id, expandFlag);`
+
+- 参数 `id` : treeTable 渲染时的 `id` 属性值
+- 参数 `expandFlag` : 折叠状态。 `true` 展开;`false` 关闭
+
+```js
+// 渲染
+treeTable.render({
+ elem: '', // 绑定元素选择器
+ id: 'test', // 自定义 id 索引
+ // 其他属性 …
+});
+// 展开或关闭全部节点
+treeTable.expandAll('test', false); // 关闭全部节点
+```
+
+设置行选中状态
+
+`treeTable.setRowChecked(id, opts);`
+
+- 参数 `id` : treeTable 渲染时的 `id` 属性值
+- 参数 `opts` : 该方法可支持的可选属性项,详见下表:
+
+| opts | 描述 | 类型 | 默认值 |
+| --- | --- | -- | --- |
+| index | 要设置选中状态的行下标或行数据 | number/object | - |
+| checked | 选中状态。`true` 选中;`false` 取消选中;`null` 切换。 其中,若为 `radio` 框,则不支持 `null`(切换)。 | boolean | - |
+| callbackFlag | 是否触发事件,若为 `true`,则 `checked: false` 无效。其对应的事件跟 `table` 的 `radio,checkbox` 事件用法一样 | boolean | `false` |
+
+```js
+// 渲染
+treeTable.render({
+ elem: '', // 绑定元素选择器
+ id: 'test', // 自定义 id 索引
+ // 其他属性 …
+});
+// 勾选或取消勾选单个节点
+treeTable.setRowChecked('test', {
+ index: 0,
+ checked: true // 选中
+});
+```
+
+设置全选或取消全选
+
+`treeTable.checkAllNodes(id, checked);`
+
+- 参数 `id` : treeTable 渲染时的 `id` 属性值
+- 参数 `checked` : 选中状态。`true` 选中;`false` 取消选中;`null` 复选框模式时的切换。
+
+```js
+// 渲染
+treeTable.render({
+ elem: '', // 绑定元素选择器
+ id: 'test', // 自定义 id 索引
+ // 其他属性 …
+});
+// 勾选或取消勾选单个节点
+treeTable.checkAllNodes('test', true); // 全选
+```
+
+获取行选中相关数据
+
+`treeTable.checkStatus(id, includeHalfCheck);`
+
+- 参数 `id` : treeTable 渲染时的 `id` 属性值
+- 参数 `includeHalfCheck` : 是否包含半选数据
+
+```js
+// 渲染
+treeTable.render({
+ elem: '', // 绑定元素选择器
+ id: 'test', // 自定义 id 索引
+ // 其他属性 …
+});
+
+treeTable.checkStatus('test', true); // 包含半选
+```
+
+
+事件
+
+`treeTable.on('event(filter)', callback);`
+
+`treeTable` 事件继承于 `table` 事件,具体使用方法可参考:[#table 事件](../table/#table.on)
+
+
+## 贴士
+
+> `treeTable` 基于 `table` 组件扩展而来,因此,熟练运用 `treeTable` 的前提是熟悉 `table` 组件。 亦可通过 `table` 提供的基础 `API` 操作 `treeTable` 组件,但 `treeTable` 无法操作 `table`。
diff --git a/docs/upload/detail/demo.md b/docs/upload/detail/demo.md
new file mode 100644
index 000000000..7795ba762
--- /dev/null
+++ b/docs/upload/detail/demo.md
@@ -0,0 +1,62 @@
+图片上传
+
+
+
+{{- d.include("/upload/examples/image.md") }}
+
+
+
+
+制作多文件上传表格
+
+
+
+{{- d.include("/upload/examples/files.table.md") }}
+
+
+
+
+过滤文件类型
+
+
+
+{{- d.include("/upload/examples/accept.md") }}
+
+
+
+
+限制文件大小
+
+
+
+{{- d.include("/upload/examples/size.md") }}
+
+
+
+选择后手动上传
+
+
+
+{{- d.include("/upload/examples/auto.md") }}
+
+
+
+
+拖拽上传
+
+
+
+{{- d.include("/upload/examples/drag.md") }}
+
+
+
+
+
+
+
+
+{{- d.include("/upload/examples/form.file.md") }}
+
+
diff --git a/docs/upload/detail/options.md b/docs/upload/detail/options.md
new file mode 100644
index 000000000..eb23927cf
--- /dev/null
+++ b/docs/upload/detail/options.md
@@ -0,0 +1,535 @@
+
+
+
+
+
+
+
+
+
+ 属性名
+ 描述
+ 类型
+ 默认值
+
+
+
+
+elem
+
+
+绑定元素选择器或 DOM 对象
+
+
+string/DOM
+-
+
+
+url
+
+
+上传接口
+
+
+string
+-
+
+
+field
+
+
+文件域的字段名
+
+
+string
+
+
+`file`
+
+
+
+
+
+
+[data](#options.data)
+
+
+
+
+
+传递给上传接口的额外参数,支持静态赋值和动态赋值两种写法。
+
+
+- 静态赋值 :
+
+```
+data: {
+ id: '123'
+}
+```
+
+- 动态赋值 :
+
+```
+data: {
+ id: function(){
+ return $('#id').val();
+ },
+ id2: function(index, file){ // 参数支持。2.9.3+
+ // 注:当 unified:true 和 ie8/9 下,参数无效
+ console.log(index); // 得到文件索引
+ console.log(file); // 得到文件对象
+ }
+}
+```
+
+
+object
+-
+
+
+headers
+
+
+上传接口的请求头。如 `headers: {token: 'abc123'}`
+
+
+object
+-
+
+
+dataType 2.8.17+
+
+
+服务端返回的数据类型,如:`text,json,xml` 等
+
+
+string
+
+
+`json`
+
+
+
+
+
+
+[accept](#options.accept)
+
+
+
+
+
+指定允许上传时校验的文件类型。可选值有:
+
+
+- `images` 图片类型
+- `file` 所有文件类型
+- `video` 视频类型
+- `audio` 音频类型
+
+
+string
+
+
+`images`
+
+
+
+
+acceptMime
+
+
+规定打开系统的文件选择框时,筛选出的文件类型,多个 `MIME` 类型可用逗号隔开。示例:
+
+```
+acceptMime: 'image/*'` // 筛选所有图片类型
+acceptMime: 'image/jpeg, image/png` // 只筛选 jpg,png 格式图片
+```
+
+更多可选值参考: MIME 类型
+
+
+string
+-
+
+
+
+
+[exts](#options.exts)
+
+
+
+
+
+
+允许上传的文件后缀。一般结合 `accept` 属性来设定。
+
+
+
+- 假设 `accept: 'file'` 类型时,那么设置 `exts: 'zip|rar|7z'` 即代表只允许上传压缩格式的文件。
+- 默认为常见图片后缀,即 `jpg|png|gif|bmp|jpeg|svg`
+
+
+string
+
+
+见左
+
+
+
+
+auto
+
+
+是否选完文件后自动上传。若为 `false`,则需设置 `bindAction` 属性来指向其它按钮提交上传。参考:[#示例](#demo-auto)
+
+
+boolean
+
+
+`true`
+
+
+
+
+bindAction
+
+
+设置触发上传的元素选择器或 DOM 对象。
+ 一般配合 `auto: false` 来使用。详细用法参考:[#示例](#demo-auto)
+
+
+string/DOM
+-
+
+
+force 2.6.9+
+
+
+规定强制返回的数据格式。
+
+- 若值为 `'json'`,则强制校验 JSON 数据格式
+
+
+string
+
+
+`null`
+
+
+
+
+size
+
+
+设置文件最大可允许上传的大小,单位 `KB` 。默认不限制。
+ 不支持 `ie8/9`
+
+
+number
+
+
+`0`
+
+
+
+
+multiple
+
+
+是否允许多文件上传。不支持 `ie8/9`
+
+
+boolean
+
+
+`false`
+
+
+
+
+unified 2.8.8+
+
+
+选择多文件时,是否统一上传,即只发送一次请求。
+
+
+boolean
+
+
+`false`
+
+
+
+
+number
+
+
+同时可上传的文件数量,一般当 `multiple: true` 时使用。
+
+
+number
+-
+
+
+drag
+
+
+是否接受拖拽的文件上传。
+
+
+boolean
+
+
+`true`
+
+
+
+
+
+
+[text](#options.text) 2.8.9+
+
+
+
+
+
+
+自定义内部各类场景下的提示文本
+
+
+
+```
+text: { // 自定义提示文本
+ "data-format-error": "", // 数据格式错误的提示
+ "check-error": "", // 文件格式校验失败的提示
+ "error": "", // 上传失败的提示
+ "limit-number": null, // 限制 number 属性的提示。若设置,需为函数写法
+ "limit-size": null, // 限制 size 属性的提示。若设置,需为函数写法
+ "cross-domain": "", // IE 下跨域的提示
+}
+```
+
+
+
+
+
+
+
+
+
+[回调函数](#options.callback)
+
+
+
+
+
+
+
+
+[choose](#options.choose)
+
+
+
+
+
+选择文件后的回调函数。返回的参数如下
+
+
+```
+choose: function(obj){
+ // 将每次选择的文件追加到文件队列
+ var files = obj.pushFile();
+
+ // 预读本地文件,如果是多文件,则会遍历。(不支持ie8/9)
+ obj.preview(function(index, file, result){
+ console.log(index); // 得到文件索引
+ console.log(file); // 得到文件对象
+ console.log(result); // 得到文件base64编码,比如图片
+
+ // obj.resetFile(index, file, '123.jpg'); // 重命名文件名
+
+ // 这里还可以做一些 append 文件列表 DOM 的操作
+
+ // obj.upload(index, file); // 对上传失败的单个文件重新上传,一般在某个事件中使用
+ // delete files[index]; //删除列表中对应的文件,一般在某个事件中使用
+ });
+}
+
+// 获取本次选取的文件,大文件建议用此方法获取文件信息(2.9.9+)
+obj.getChooseFiles();
+```
+
+详细用法参考:[#示例](#demo-files-table)
+
+
+
+
+
+
+[before](#options.before)
+
+
+
+
+
+文件提交上传前的回调函数。返回的参数同 choose
+
+
+```
+before: function(obj){ // obj 参数同 choose
+ layer.load(); // 上传 loading
+
+ // 若返回 false,则表明阻止上传
+ /*
+ if(true){
+ return false;
+ }
+ */
+}
+
+// 返回 jQuery Deferred 对象或 JS 原生 Promise 对象,false 或 Promise.reject 表明阻止上传(2.9.11+)
+// Promise
+/** @type {(obj: object) => boolean | JQueryDeferred | Promise} */
+before: function(obj){
+ return new Promise(function(resolve, reject){
+ setTimeout(function(){
+ console.log('before_async_task', obj);
+ resolve(true);
+ }, 1000)
+ })
+}
+
+// Deferred
+before: function(obj){
+ return $.Deferred(function(defer){
+ setTimeout(function(){
+ console.log('before_async_task', obj);
+ defer.resolve(true);
+ }, 1000)
+ }).promise();
+}
+
+// Deferred2
+before: function(obj){
+ var defer = $.Deferred();
+ setTimeout(function(){
+ console.log('before_async_task', obj);
+ defer.resolve(true);
+ }, 1000)
+ return defer.promise();
+}
+```
+
+
+
+
+
+
+[progress](#options.progress)
+
+
+
+
+
+执行上传请求后的回调函数。返回的参数如下:
+
+
+```
+progress: function(n, elem, res, index){
+ var percent = n + '%' // 获取进度百分比
+ element.progress('demo', percent); // 可配合 layui 进度条元素使用
+
+ // 得到当前触发的元素 DOM 对象
+ console.log(elem); // 可通过该元素定义的属性值匹配到对应的进度条。
+ console.log(res); // 得到 progress 响应信息
+
+ console.log(index); // 得到当前上传文件的索引,多文件上传时的进度条控制
+ element.progress('demo-'+ index, n + '%'); // 进度条
+}
+```
+
+详细用法参考:[#示例](#examples)
+
+
+
+
+
+[done](#options.done)
+
+
+
+
+
+执行单次文件上传请求后的回调函数。返回的参数如下:
+
+
+```
+done: function(res, index, upload){
+ // 假设 `code: 0` 代表上传成功
+ if(res.code == 0){
+ // do something // 比如将 res 返回的图片链接保存到隐藏域
+ }
+
+ // 获取当前触发上传的元素,一般用于 elem 绑定 class 的情况
+ var item = this.item;
+
+ // …
+}
+```
+
+详细用法参考:[#示例](#examples)
+
+
+
+
+
+
+
+[allDone](#options.allDone)
+
+
+
+
+
+
+当开启多文件 (`multiple: true` ) 且所有文件均上传完毕后的状态回调函数。
+
+
+
+```
+allDone: function(obj){
+ console.log(obj.total); // 上传的文件总数
+ console.log(obj.successful); // 上传成功的文件数
+ console.log(obj.failed); // 上传失败的文件数
+}
+```
+
+
+
+
+error
+
+
+执行上传请求出现异常的回调(一般为网络异常、URL 404等)。返回三个参数如下:
+- `index`: 当前文件的索引
+- `upload`: 重新上传的方法
+- `res`: 返回值(纯文本)2.9.12+
+- `xhr`: jQuery XHR 对象 2.9.15+
+
+```
+error: function(index, upload, res, xhr){
+ console.log(index); // 当前文件的索引
+ // upload(); 重新上传的方法
+ console.log(res); // 返回值(纯文本)
+ console.log(JSON.parse(res)); // 返回值(json)
+ console.log(xhr);
+}
+```
+
+
+
+
+
+
diff --git a/docs/upload/examples/accept.md b/docs/upload/examples/accept.md
new file mode 100644
index 000000000..85ca16fe8
--- /dev/null
+++ b/docs/upload/examples/accept.md
@@ -0,0 +1,40 @@
+
+
+
+ 上传文件
+
+
+
+ 只允许压缩文件
+
+
+
+ 上传视频
+
+
+
+ 上传音频
+
+
+
+
+
diff --git a/docs/upload/examples/auto.md b/docs/upload/examples/auto.md
new file mode 100644
index 000000000..a13020177
--- /dev/null
+++ b/docs/upload/examples/auto.md
@@ -0,0 +1,24 @@
+
+ 选择文件
+ 开始上传
+
+
+
+
diff --git a/docs/upload/examples/drag.md b/docs/upload/examples/drag.md
new file mode 100644
index 000000000..beb67bb28
--- /dev/null
+++ b/docs/upload/examples/drag.md
@@ -0,0 +1,28 @@
+
+
+
点击上传,或将文件拖拽到此处
+
+
+
+
+
+
+
+
diff --git a/docs/upload/examples/files.table.md b/docs/upload/examples/files.table.md
new file mode 100644
index 000000000..2aa8bba52
--- /dev/null
+++ b/docs/upload/examples/files.table.md
@@ -0,0 +1,100 @@
+
+
选择多文件
+
+
+
+
+
+
+
+
+
+ 文件名
+ 大小
+ 上传进度
+ 操作
+
+
+
+
+
开始上传
+
+
+
+
+
diff --git a/docs/upload/examples/form.file.md b/docs/upload/examples/form.file.md
new file mode 100644
index 000000000..2b7cc9df7
--- /dev/null
+++ b/docs/upload/examples/form.file.md
@@ -0,0 +1,19 @@
+
+
+
+
\ No newline at end of file
diff --git a/docs/upload/examples/image.md b/docs/upload/examples/image.md
new file mode 100644
index 000000000..3a4a137b5
--- /dev/null
+++ b/docs/upload/examples/image.md
@@ -0,0 +1,88 @@
+
+ 单图片上传
+
+
+
+
+
+
+
+
+
+
+
+ 多图片上传
+
+
+ 预览图:
+
+
+
+
+
+
diff --git a/docs/upload/index.md b/docs/upload/index.md
new file mode 100644
index 000000000..6ee35b986
--- /dev/null
+++ b/docs/upload/index.md
@@ -0,0 +1,128 @@
+---
+title: 上传组件 upload
+toc: true
+---
+
+# 上传组件
+
+> 上传组件 `upload` 是用于处理文件上传的前端交互逻辑,可以更好地协助后端实现文件从本地到服务端上传的对接。
+
+示例
+
+以下示例均没有设置上传接口,因此每次上传都会报异常提示,这属于正常现象。实际使用时设置成您的真实上传接口即可。
+
+
+
+
+{{- d.include("/upload/detail/demo.md") }}
+
+
+
+
+API
+
+| API | 描述 |
+| --- | --- |
+| var upload = layui.upload | 获得 `upload` 模块。 |
+| [var inst = upload.render(options)](#render) | upload 组件渲染,核心方法。 |
+| [inst.upload()](#upload) | 对当前实例提交上传 |
+| [inst.reload(options)](#reload) | 对当前实例进行重载 |
+| inst.config | 获得当前实例的属性选项 |
+
+渲染
+
+`upload.render(options);`
+
+- 参数 `options` : 基础属性选项。[#详见属性](#options)
+ 注 : 除 `elem` 属性外,其他基础属性也可以直接写在元素的 `lay-options="{}"` 属性中。
+
+```
+上传
+上传
+上传
+
+
+
+```
+
+该方法返回一个实例对象,包含操作当前实例的相关方法成员。
+
+```
+var inst = upload.render(options);
+console.log(inst); // 得到当前实例对象
+```
+
+提交上传
+
+`inst.upload();`
+
+- 无需传递参数
+
+文件在进行选择后,会自动提交上传。而若文件*上传失败*,则可以使用该方法来重新上传,
+
+```
+// 渲染
+var inst = upload.render({
+ elem: '#id',
+ error: function(){ // 上传失败的回调
+ // 当上传失败时,可在此处生成「重新上传」按钮,并执行该方法重新触发上传提交
+ /*
+ $('#btn').on('click', function(){
+ inst.upload();
+ })
+ */
+ }
+ // …
+});
+```
+
+重载
+
+`inst.reload(options);`
+
+- 参数 `options` : 基础属性选项。[#详见属性](#options)
+
+该方法用于对当前的上传实例进行完整重载,所有属性均可参与到重载中。
+
+```
+// 渲染
+var inst = upload.render({
+ elem: '#id',
+ // …
+});
+
+// 重载
+inst.reload({
+ field: 'AAA',
+ // …
+})
+```
+
+属性
+
+
+{{- d.include("/upload/detail/options.md") }}
+
+
+跨域方案
+
+`upload` 组件支持跨域上传,一般有以下两种场景
+
+- 自建上传服务。在服务端配置 `CORS` 开启跨资源共享。 即对接口所在的服务器设置 `Access-Control-Allow-Origin ` 相关 `header` 信息。
+
+- 第三方上传服务。如:阿里云、腾讯云等,只需按照不同平台对应的上传 SDK 进行操作即可。
+
diff --git a/docs/util/detail/demo.md b/docs/util/detail/demo.md
new file mode 100644
index 000000000..ad2933c25
--- /dev/null
+++ b/docs/util/detail/demo.md
@@ -0,0 +1,129 @@
+
+
+倒计时
+
+请选择要计算的日期:
+
+
+
+
+
+某个时间在多久前
+
+请选择要计算的日期:
+
+
+
+
+
+转换日期格式
+
+请编辑格式:
+
+
+
+
+
+转义 HTML
+
+
+ <textarea class="lay-textarea" id="test7">
+
HTML Title
+<script>
+ alert(0);
+</script>
+ </textarea>
+
+
+ 转义
+ 还原
+
+
+
+
+
+
+
diff --git a/docs/util/index.md b/docs/util/index.md
new file mode 100644
index 000000000..c5ad55dd2
--- /dev/null
+++ b/docs/util/index.md
@@ -0,0 +1,265 @@
+---
+title: 工具模块 util
+toc: true
+---
+
+# 工具模块
+
+> 工具模块 `util` 是由工具类方法和小组件组成的集合。
+
+示例
+
+
+{{- d.include("/util/detail/demo.md") }}
+
+
+
+
+API
+
+| API | 描述 |
+| --- | --- |
+| var util = layui.util | 获得 `util` 模块。 |
+| [util.fixbar(options)](../fixbar/) | 固定条组件 |
+| [util.countdown(options)](#countdown) | 倒计时组件 |
+| [util.timeAgo(time, onlyDate)](#timeAgo) | 某个时间在多久前 |
+| [util.toDateString(time, format, options)](#toDateString) | 将毫秒数或日期对象转换成日期格式字符 |
+| [util.digit(num, length)](#digit) | 数字前置补零 |
+| [util.escape(str)](#escape) | 转义 HTML 字符 |
+| [util.unescape(str)](#escape) | 还原 HTML 字符 |
+| [util.openWin(options)](#openWin) 2.8+ | 打开浏览器新标签页 |
+| [util.on(attr, events, options)](#on) | 批量事件处理 |
+
+倒计时
+
+`util.countdown(options);`
+
+- 参数 `options` 2.8.9+ : 属性选项。可选项详见下表:
+
+| 属性 | 描述 |
+| --- | --- |
+| date | 目标时间值。值可以为毫秒数或 `Date` 对象 |
+| now | 当前时间值,一般为当前服务器时间。值可以为毫秒数或 `Date` 对象 |
+| ready | 倒计时初始时的回调函数。 |
+| clock | 倒计时计时中的回调函数,每秒触发一次,直到计时完成。 |
+| done | 倒计时计时完成的回调函数,即到达目标时间值时触发 |
+
+- 注: 2.8.9 之前的版本写法为:`util.countdown(date, now, clock);`
+
+该方法返回的实例对象成员如下 2.8.9+ :
+
+```js
+var countdown = util.countdown(options);
+countdown.clear(); // 清除当前倒计时
+countdown.reload(options); // 重载当前倒计时。
+countdown.timer; // 当前倒计时计时器 ID
+```
+
+相关用法可参考:[#示例](#examples)
+
+```js
+layui.use('util', function(){
+ var util = layui.util;
+ // 示例
+ util.countdown({
+ date: '2099-1-1', // 目标时间值
+ now: new Date(), // 当前时间,一般为服务器时间,此处以本地时间为例
+ clock: function(obj, countdown){ // 计时中
+ console.log(obj); // 得到当前计时器的「天、时、分、秒」值
+ console.log(countdown); // 得到当前实例对象
+ },
+ done: function(obj, countdown){ // 计时完成
+ console.log('time is up');
+ }
+ });
+});
+```
+
+某个时间在多久前
+
+`var result = util.timeAgo(time, onlyDate);`
+
+- 参数 `time` : 某个时间的毫秒数或日期对象
+- 参数 `onlyDate` : 是否在超过 30 天后,只返回日期字符,而不返回时分秒
+
+返回结果
+
+- 若 `time` 在 3 分钟以内,返回: 刚刚
+- 若 `time` 在 30 天以内,返回: 若干分钟前、若干小时前、若干天前,如:5 分钟前
+- 若 `time` 在 30 天以上,返回: 日期字符,如: 2023-01-01
+
+```
+var result = util.timeAgo(1672531200000); // 2023-01-01 00:00:00
+```
+
+相关效果见:[#示例](#examples)
+
+
+转换日期格式字符
+
+`var result = util.toDateString(time, format, options);`
+
+- 参数 `time` : 毫秒数或日期对象
+- 参数 `format` : 日期字符格式。默认格式:`yyyy-MM-dd HH:mm:ss` 。可自定义,如: `yyyy年MM月dd日`
+- 参数 `options` 2.8.13+ : 该方法的属性选项,详见下表:
+
+| 属性名 | 描述 | 类型 | 默认值 |
+| --- | --- | --- | --- |
+| customMeridiem | 自定义 meridiem 格式 | Function | - |
+
+```
+var result = util.toDateString(1672531200000, 'yyyy-MM-dd'); // 2023-01-01
+
+// 中括号中的字符会原样保留 2.8.13+
+var result2 = util.toDateString(new Date('2023-01-01 11:35:25'), 'ss[s]'); // 25s
+
+// 自定义 meridiem
+var result3 = util.toDateString(
+ '2023-01-01 11:35:25',
+ 'hh:mm:ss A',
+ {
+ customMeridiem: function(hours, minutes){
+ return (hours < 12 ? 'AM' : 'PM')
+ //.split('').join('.') // 有句点,A.M.
+ //.toLowerCase() // 小写,a.m.
+ }
+ }
+); // 11:35:25 AM
+```
+
+参数 `format` 所有可用的格式列表 :
+
+| 格式 | 示例 | 描述 |
+| --- | --- | --- |
+| yy 2.8.13+ | 23 | 年,两位数 |
+| yyyy | 2023 | 年,四位数 |
+| M 2.8.13+ | 1-12 | 月 |
+| MM | 01-12 | 月,两位数 |
+| d 2.8.13+ | 1-31 | 日 |
+| dd | 01-31 | 日,两位数 |
+| H 2.8.13+ | 0-23 | 小时 |
+| HH | 00-23 | 小时,两位数 |
+| h 2.8.13+ | 1-12 | 小时,12 小时制 |
+| hh 2.8.13+ | 01-12 | 小时,12 小时制,两位数 |
+| A 2.8.13+ | 凌晨/早上/上午/中午/下午/晚上 | meridiem |
+| m 2.8.13+ | 0-59 | 分钟 |
+| mm | 00-59 | 分钟,两位数 |
+| s 2.8.13+ | 0-59 | 秒 |
+| ss | 00-59 | 秒,两位数 |
+| SSS 2.8.13+ | 000-999 | 毫秒,三位数 |
+
+数字前置补零
+
+`util.digit(num, length);`
+
+- 参数 `num` : 原始数字
+- 参数 `length` : 数字长度,如果原始数字长度小于 length,则前面补零
+
+该方法返回一个 `string` 类型的结果,如:
+
+```
+var rs1 = util.digit(6, 2); // "06"
+var rs2 = util.digit(7, 3); // "007"
+```
+
+
+转义和还原 HTML
+
+- `util.escape(str);` 转义 HTML
+- `util.unescape(str);` 还原被转义的 HTML
+
+参数 `str` : 任意 HTML 字符
+
+```
+var str1 = util.escape('123
'); // 返回: <div>123</div>
+var str2 = util.unescape('<div>123</div>'); // 返回: 123
+```
+
+打开浏览器新标签页 2.8+
+
+`util.openWin(options);`
+
+- 参数 `options` : 属性选项。可选项详见下表
+
+| 属性 | 描述 |
+| --- | --- |
+| url | 要打开页面 `URL` |
+| target | 打开页面的方式或窗口 `name` |
+| content | 打开的页面内容。若设置了 `url` 属性,则该属性无效 |
+| specs | 窗口的相关配置,同 `window.open()` 的 `specs` |
+| window | 当前所在的窗口对象,默认 `self` |
+
+该方法基于原生 `window.open()` 的二次封装,以提升打开浏览器窗口的灵活性。
+
+```
+// 打开一个 url
+util.openWin({
+ url: 'https://cn.bing.com'
+});
+// 打开一个自定义内容窗口
+util.openWin({
+ content: 'Hello World.'
+});
+```
+
+批量事件处理
+
+`util.on(attr, events, options);`
+
+| 参数 | 描述 | 类型 | 默认值 |
+| --- | --- | --- | --- |
+| attr | 触发事件的元素属性名。可省略2.9+ | `string` | `lay-on` |
+| events | 事件集合。包含 `attr` 对应的属性值和事件回调函数的键值对 | `object` | - |
+| options 2.9+ | 参数的更多选项。详见下表。 | `object` | - |
+
+参数 `options` 可选项:
+
+| options | 描述 | 类型 | 默认值 |
+| --- | --- | --- | --- |
+| elem | 触发事件的委托元素 | string \| HTMLElement \| JQuery | - |
+| trigger | 事件触发的方式 | string | `click` |
+
+
+
+
+ 事件 1
+ 事件 2
+ 事件 3
+
+
+
+
+
+
+
diff --git a/docs/versions.md b/docs/versions.md
new file mode 100644
index 000000000..4b6a63a47
--- /dev/null
+++ b/docs/versions.md
@@ -0,0 +1,65 @@
+---
+title: 更新日志
+toc: true
+---
+
+# 更新日志
+
+> 导读:📑 [Layui 不同版本的浏览器兼容说明](/notes/browser-support.html) · 📑 [Layui 2.x 系列版本主要升级变化](/notes/share/2x-major-upgrade-changes.html) · 📑 [Layui 2.8+ 《升级指南》](/notes/2.8/upgrade-guide.html)
+
+
+
+
+
+
+
+ v3.0.0-alpha
+
+
+- https://github.com/layui/layui/releases/tag/v3.0.0-alpha.3
+- https://github.com/layui/layui/releases/tag/v3.0.0-alpha.2
+- https://github.com/layui/layui/releases/tag/v3.0.0-alpha.1
+- https://github.com/layui/layui/releases/tag/v3.0.0-alpha.0
+
+---
+
+
+
+
+
+查看 2.x 系列版本更新日志
diff --git a/docs/versions/2.8.x.md b/docs/versions/2.8.x.md
new file mode 100644
index 000000000..37187a84e
--- /dev/null
+++ b/docs/versions/2.8.x.md
@@ -0,0 +1,699 @@
+---
+title: 2.8.x 更新日志
+toc: true
+---
+
+# 更新日志
+
+> 导读:📑 [Layui 2.8+ 《升级指南》](/notes/2.8/upgrade-guide.html) · 📑 [Layui 新版文档站上线初衷](/notes/2.8/news.html)
+
+
+
+查看 2.10+ 及最新版更新日志
+
+---
+
+
+
+查看 2.9.x 系列版本更新日志
+
+---
+
+
+
+
+ 2.8.18
+ 2023-10-31
+
+
+- #### form
+ - 新增 `input` 数字输入框组件的特定属性 `lay-precision`,用于设置数值精度 # 1375/I81SY4
+ - 优化 `input` 数字输入框组件的失去焦点对值的有效范围约束 # 1375/I7KU6V
+ - 优化 `input` 数字输入框组件当值达到临界点时加减按钮的禁用视觉效果 # 1375
+ - 优化 `input` 数字输入框当表单验证失败时的边框颜色 # 1371
+- #### nav
+ - 新增 垂直导航菜单展开和收缩时的过渡动画 # 1407
+ - 新增 `lay-accordion` 属性支持,用于开启手风琴,兼容旧版 `lay-shrink="all"` # 1384
+- #### layer
+ - 新增 `photos` 层的鼠标滚轮缩放功能 # I7ZAE8
+ - 优化 移动端定位 # 1376
+- #### table
+ - 新增 `complete` 属性,当数据接口请求完成后执行,无论成功还是失败均会触发 # 1379
+ - 修复 `ignoreExport` 表头属性值效果与文档不符的问题 # I86DBY
+ - 修复 `type: 'radio'` 且为右侧固定列时,选择效果无效的问题 # 1406
+ - 优化 鼠标在固定列滚轮时无法触发滚动条的问题 # I8CGZH
+ - 优化 某些情况在 Firefox 的报错问题
+- #### treeTable
+ - 修复 `treeTable.removeNode()` 在开启 `data` 模式时删除异常问题 # I7Z0AB/I82E2S
+ - 修复 `treeTable.setRowChecked()` 方法未逐层展开上级节点的问题 # 1385/I84RUT
+ - 修复 `treeTable.addNodes()` 新增根节点时出现的报错问题 # 1414
+ - 修复 数据格式为简单类型时 IE9+ 兼容问题 # 1415/I8C04Y
+- #### upload
+ - 修复 `unified: true` 时的报错问题 # 1391
+ - 优化 渲染入口逻辑,以解决因重复渲染导致的若干问题 # 1391
+ - 优化 实例的 `reload` 方法,可更好地进行完整重载 # 1391
+- #### dropdown / menu
+ - 新增 `accordion` 属性,开启手风琴效果(menu: 主容器设置 `lay-accordion` 属性) # 1397
+ - 新增 折叠展开动画效果 # 1397
+- #### laydate
+ - 优化 `rangeLinked` 属性开启时,点击目标元素可重新渲染的问题 # 1391
+ - 优化 `type` 为 `time,datetime` 选择器时,「现在」按钮的禁用状态判断条件 # I828CD
+- #### laypage
+ - 新增 `limitTemplet` 属性,用于自定义条目模板 # I80AHZ
+ - 新增 `skipText` 属性,用于自定义跳页区域文本 # I80AHZ
+- #### carousel
+ - 优化 轮播切换时的动画效果 # 1378/I82STP
+- #### rate / slider
+ - 优化 代码细节 # 1374
+- #### code
+ - 新增 `code` 属性,用于设置原始 code 值,优先级高于目标元素中的内容 # 1391
+ - 优化 预览区域显示效果 # 1398
+ - 优化 其他若干小问题 # 1391
+- #### 其他
+ - 新增 Source Maps 支持 # 1404/I89W5P
+ - 新增 lay 模块部分函数 JSDoc 注释和示例 #1401
+ - 优化 ` ` 全局样式优先级 # I86R6G
+
+### 下载: [layui-v2.8.18.zip](https://gitee.com/layui/layui/attach_files/1570299/download)
+
+---
+
+
+ 2.8.17
+ 2023-09-11
+
+
+- #### 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)
+
+---
+
+
+ 2.8.16
+ 2023-08-30
+
+
+- #### layer
+ - 新增 `photos` 的 `toolbar` 属性,用于开启图片旋转 放大 缩小 还原等头部工具栏 # 1339
+ - 调整 `photos` 的 属性名: `hideFooter → footer`,用于是否开启底部栏
+- #### table
+ - 优化 初始化时的样式渲染及多行模式的内容结构
+ - 优化 `size` 为 `sm` / `lg` 时的展开状态
+ - 优化 无数据时的导出和打印功能提示 # 1337
+ - 优化 数据项为禁用状态的选中状态 # 1328
+ - 优化 `table.renderData()` 方法执行了多余排序的问题 # 1358
+- #### treeTable
+ - 修复 部分操作之后 `radio` 列选中状态丢失的问题 # 1358
+ - 修复 `data` 模式下排序之后出现节点结构错乱的问题 # 1358/I7TXXL
+ - 优化 `data.cascade` 属性,新增 `none` 可选值,即操作节点时不做任何联动 # 1358
+ - 优化 数据项为禁用状态时的全选复选框的状态 # 1329
+ - 优化 异步加载子节点为空时的展开状态 # 1326
+- #### laydate
+ - 优化 `shortcuts.value` 快捷选项的赋值属性,支持函数类型 # 1324
+- #### rate
+ - 优化 代码书写格式 # 1343
+- #### code
+ - 修复 自定义工具栏出现的报错问题 # 1342
+ - 优化 复制功能,以兼容非安全域下复制失败的问题 #1356
+ - 优化 预览区未能显示滚动条的问题 # 1359
+
+### 下载: [layui-v2.8.16.zip](https://gitee.com/layui/layui/attach_files/1511975/download)
+
+---
+
+
+ 2.8.15
+ 2023-08-16
+
+
+- #### table
+ - 新增 `expandedWidth` 表头属性,用于设置单元格被展开后的宽度
+ - 优化 单元格内容下拉展开状态面板,以解决此前因展开后内容不可操作等问题 # I7RS8S
+ - 优化 `table.reload()` 造成 `window resize` 事件重复绑定的问题 # I7RJWY
+ - 优化 多行模式在 Firefox 的内容显示问题
+- #### layer
+ - 优化 开启默认动画弹出层后,鼠标移入按钮出现往上偏移的问题 # I7QVVP
+ - 优化 弹层右上角关闭按钮因上个版本更新导致的主题样式异常问题 # I7TP11
+- #### dropdown
+ - 新增 `customName` 属性,用于自定义 `data` 属性中常用的字段名称
+ - 修复 在某些特殊情况下调整浏览器窗口尺寸时出现的 `resize` 事件报错问题
+- #### tree
+ - 新增 `customName` 属性,用于自定义 `data` 中常用的字段名称
+- #### lay
+ - 新增 `lay.style()` 方法,用于向页面创建 style 样式
+ - 优化 `lay.position()` 方法,可让下拉弹出元素的定位更智能
+
+### 下载: [layui-v2.8.15.zip](https://gitee.com/layui/layui/attach_files/1499232/download)
+
+---
+
+因 `2.8.14` 版本存在 layer 主题样式异常问题,`2.8.14` 已被跳过。
+
+---
+
+
+ 2.8.13
+ 2023-08-08
+
+
+- #### table
+ - 优化 在自定义模板中放置 `checkbox` 时对应的文字显示异常问题 # I7LQNO
+ - 优化 `totalRow` 属性在 `table.reloadData()` 数据重载时的支持 # I7R6VY
+- #### treeTable
+ - 修复 执行 `treeTable.addNodes()` 增加节点导致当前节点选中状态丢失的问题 # I7Q6IP
+ - 优化 删除节点时,对容器尺寸重新进行自动适配
+- #### tree
+ - 优化 容器样式,以解决用于其他组件内部可能造成的样式异常问题 # I7QAO3
+- #### dropdown
+ - **调整** `data.title` 属性对 HTML 的转义处理。若不转义,可通过 `templet` 属性实现 # I7Q6IV
+- #### util
+ - 重构 `util.toDateString()` 转换日期格式字符组件,以提供更强大的占位符支持 # 1314
+ - 修复 `util.fixbar()` 组件因 `default` 属性在 IE8 出现的保留字报错问题
+
+### 下载: [layui-v2.8.13.zip](https://gitee.com/layui/layui/attach_files/1490273/download)
+
+---
+
+
+
+ 2.8.12
+ 2023-08-01
+
+
+- #### form
+ - 优化 `input` 数字输入框在前置后置结构中的样式 # I7KTQB
+- #### layer
+ - 修复 设置 `scrollbar` 属性禁用页面滚动条时,点击最大化再还原导致滚动条又重新出现的问题 # I7NTGX
+ - 修复 弹层容器中的 `id` 值与其他弹层索引值相同时,导致关闭弹层存在冲突问题 # I7PF0O
+- #### upload
+ - 修复 `auto: false` 时,打开文件选择框并点击取消后,导致文件上传失效的问题 # I7NU31
+- #### treeTable
+ - 新增 `tree.data.cascade` 属性,用于设置复选的级联方式,默认 `all` # 1309
+ - 修复 右侧固定列选中背景色没有和主体选中状态保持同步的问题 # I7NVCU
+ - 调整 树形转平铺的方法,保留节点的 `children` 信息 # 1309
+ - 调整 重载时的参数拷贝,由默认深拷贝换成默认浅拷贝,以便与 table 组件保持一致 # 1309/I7NN0O
+- #### tree
+ - 优化 `checked` 属性赋值机制,若初始数据源存在该属性,才对其进行动态赋值
+ - 优化 `spread` 属性赋值机制,若初始数据源存在该属性,则展开和收缩时,自动对其更新状态值
+- #### 其他
+ - 修正 code 中部分单词拼写错误 # 1310
+
+### 下载: [layui-v2.8.12.zip](https://gitee.com/layui/layui/attach_files/1482367/download)
+
+---
+
+
+ 2.8.11
+ 2023-07-13
+
+
+- #### form
+ - 修复 `radio` 标题模板中若存在图标,选中时该图标被强制更改的问题 # I7IERB
+ - 优化 `input` 数字输入框的精度问题 # I7I7J2
+ - 修正 `verIncludelRequired` 属性名为 `verIncludeRequired` # 1305
+- #### table
+ - 修复 导出统计行中若存在逗号出现的内容分隔异常问题 # I7IDA3
+ - 修复 当点击筛选显示隐藏固定列时出现的未对齐的问题 # I7KQ0O
+- #### menu
+ - 修复 `menu` 标题项自定义图标在展开收缩后被强制更改的问题 # 1303/I7JAPU
+- #### tree
+ - 修复 点击复选框时未将对应的数据中的 `checked` 属性值进行同步的问题
+
+### 下载: [layui-v2.8.11.zip](https://gitee.com/layui/layui/attach_files/1464525/download)
+
+---
+
+
+ 2.8.10
+ 2023-07-03
+
+
+- 修复 `layui.js` 在 IE 和 Safari 等「古董浏览器」存在一个正则零宽断言报错的问题 # I7HZCZ/I7I0TO
+
+### 下载: [layui-v2.8.10.zip](https://gitee.com/layui/layui/attach_files/1455365/download)
+
+---
+
+
+ 2.8.9
+ 2023-07-03
+
+
+- #### form
+ - 新增 `input` 数字输入框组件,通过动态点缀 `lay-affix="number"` 属性开启
+ - 优化 `input,textarea` 禁用状态时的样式 # I7GN5Z
+- #### table
+ - 优化 点击单元格出现编辑框时,不触发行事件
+- #### treeTable
+ - 修复 选中和取消选中时,父节点和子节点的选中背景色未能正确同步的问题 # I7FUD6
+- #### upload
+ - 新增 `text` 属性,用于自定义内部各类场景下的提示文本
+- #### util
+ - 重构 `countdown` 倒计时组件,采用 `options` 参数写法,但仍对旧版兼容
+ - 新增 `countdown` 的 `date,now,clock,done` 等属性
+ - 新增 `countdown` 的 `clear,reload` 等实例方法,用于清除和重置倒计时等操作
+
+### 下载: [~~layui-v2.8.9.zip~~](https://gitee.com/layui/layui/attach_files/1454465/download)
+
+---
+
+
+ 2.8.8
+ 2023-06-20
+
+
+- #### form
+ - 新增 `input` 获取焦点时的光环效果,以提升当前活动输入框的辨别度
+ - 取消 上个版本对 `select` 开启搜索时 `value` 的改动,由于存在若干不可控的影响
+- #### table
+ - 新增 `colTool` 事件,点击表头自定义元素触发,并返回当前列的相关信息,提升 table 的可玩性
+ - 新增 `row,tool,checkbox,radio` 事件返回的 `dataCache` 属性,可获得当前行缓存数据,包含特定字段
+- #### upload
+ - 新增 `unified` 属性,用于选择多文件时是否统一上传,即只发送一次请求 # I6Z171
+- #### 其他
+ - 优化 `layui.js,layer.js` 部分代码细节 # 1285
+
+### 下载: [layui-v2.8.8.zip](https://gitee.com/layui/layui/attach_files/1444541/download)
+
+---
+
+
+ 2.8.7
+ 2023-06-16
+
+
+- #### form
+ - ~~优化 `select` 开启搜索时输入状态,将值转移到 `placeholder`,便于输入~~ # 1280
+ *注:由于存在若干影响,该项功能已在 `2.8.8` 中取消*
+- #### table
+ - 新增 表头复选框的半选效果,当数据项部分选中且未全选时显示
+ - 优化 `table.setRowChecked()` 方法,新增当前行选中背景色,便于与 hover 等活动背景色区分
+ - 剔除 `table.setRowChecked()` 方法中的 `selectedStyle` 属性,因为没有实质意义
+ - 优化 表头部分字段为 `hide` 在数据异常的情况下可能出现的表头错位的问题 # 1281
+ - 优化 `done` 回调函数,新增参数 `origin` 用于区分重载和重新渲染数据 # 1281
+ - 加强 `ignoreExport` 表头属性,允许指定不排除哪些字段 # 1281
+- #### treeTable
+ - 新增 `view.expandAllDefault` 属性,用于设置是否默认展开全部节点 # 1281
+ - 修复 开启排序且在 `done` 回调中执行了 `expandAll` 展开全部导致死循环问题 # 1281
+ - 修复 执行 `treeTable.reload(id)` 若 `id` 未匹配到对应实例时出现的报错问题 # 1281/I7CXLN
+- #### grid
+ - 修复 space30 和 space32 边距相同的问题 # I7D7YP
+
+### 下载: [layui-v2.8.7.zip](https://gitee.com/layui/layui/attach_files/1441026/download)
+
+---
+
+
+ 2.8.6
+ 2023-06-08
+
+
+- #### table
+ - 新增 `table.renderData(id)` 方法,用于重新渲染数据,可搭配 `table.cache` 使用 # 1273
+ - 修复 `table.hideCol(id, cols)` 第二个参数为普通对象时的异常问题 # 1270/I7AAUN
+ - 修复 多级表头在某些缩放比例的情况下出现表头跟表体错位问题 # 1273/I7A33T
+ - 修复 `table.getTrHtml()` 方法 `tr` 节点代码中的 `numbers` 列信息错误问题
+ - 优化 `table setRowChecked()` 方法中标注当前选中行样式的判断逻辑 # 1273
+- #### treeTable
+ - 修复 `treeTable.expandAll()` 展开全部之后节点的折叠状态没有记忆的问题 # 1273
+ - 修复 无主键的树表 reloadData 之后节点被展开的问题 # 1273
+ - 修复 部分情况下父节点展开之后子节点中的单选复选列和其他表单元素没有渲染的问题 1273/I7AWNV
+ - 修复 初始化无数据时出现的数据报错的问题 # 1273
+- #### tab
+ - 修复 删除选项卡时,若标题栏存在其他元素,下标获取异常的问题 # 1271/I7AO7F
+ - 优化 `element.tabAdd()` 方法,第二个参数中新增 `change` 属性支持,以支持添加即自动切换功能
+ - 优化 折叠功能,切换选项时不自动折叠选项卡,且添加选项时若处于折叠状态则自动展开 # I79HUD
+- #### util
+ - 修复 fixbar 中添加了无效样式问题 # I79JTH
+
+### 下载: [layui-v2.8.6.zip](https://gitee.com/layui/layui/attach_files/1432770/download)
+
+---
+
+因 `2.8.5` 版本中存在一个 tab 删除时下标的异常问题,`2.8.5` 已被跳过。
+
+---
+
+
+ 2.8.4
+ 2023-05-30
+
+
+- #### form
+ - 新增 `verIncludelRequired` 全局属性,用于设置验证规则中是否同时包含必填 # I737EW
+ - 修复 checkbox 开关标题和半选图标未垂直居中的问题 # 1255
+ - 修复 checkbox 在初始设置半选时,点击复选框时图标未恢复成非半选状态的问题
+ - 修复 checkbox 被重新渲染时,标题模版未正确获取的问题 # 1257
+ - 修复 select 经浏览器翻译成别的语言后,点击选项出现的显示异常问题 # 1256
+ - 优化 checkbox 元素的 `lay-skin` ,当设置非内置风格时,不再强制显示为默认风格
+- #### table
+ - 新增 对 table 内元素的 `lay-unrow` 属性的识别,点击该元素时,可阻止执行 `row` 行单击事件
+ - 修复 `table.setRowChecked()` 方法导致 `checkbox,radio` 事件失效的问题 # I73MLV/I76KBX/I78VI3
+ - 修复 打印功能在 Edge 中可能出现的闪退问题 # 1264
+ - 优化 `table.setRowChecked()` 方法,若未传 `checked` 属性,则自动对 `checkbox` 进行选中状态值切换
+ - 优化 `row` 事件机制,若目标元素为 `checkbox,radio`,则不触发 `row` 事件
+ - 优化 外层容器的高度,不再设置一个固定值,内部元素将根据 `height` 属性值自动撑满
+ - 优化 底部边框问题
+- #### treeTable
+ - 新增 节点折叠状态记忆功能 # 1260/I777CJ
+ - 新增 `customName.icon` 属性,用于自定义图标的属性名称 # 1260/I73BQU
+ - 新增 `async.format` 回调函数,用于处理异步子节点数据,优先级高于 `async.url` # 1260
+ - 新增 `treeTable.reloadAsyncNode(id, index)` 方法,用于重载异步子节点 # 1260
+ - 新增 `treeTable.getNodeById(id)` 方法,用于获取节点信息集 # 1260
+ - 新增 `treeTable.getNodesByFilter(id, filter, opts)` 方法,用于获取符合过滤规则的节点信息集 # 1260
+ - 修复 `isSimpleData` 模式渲染后的默认数据排序异常问题 # 1260
+ - 修复 展开全部节点排序失效的问题 # 1260/I73M2K
+ - 修复 折叠叶子节点时,图标没有变化的问题 # 1260
+ - 修复 节点选中状态判断异常问题 # 1260
+ - 优化 `treeTable.checkStatus()` 方法,可通过设置第二个参数,用于是否返回半选状态的数据 # 1260/I73JAW
+ - 优化 重新排序和视图内表单初始化的调用逻辑 # 1260
+ - 优化 节点渲染方法 # 1260
+- #### layer
+ - 修复 `skin:'layui-layer-lan'` 时,导致 `btnAlign` 属性无效的问题 # I73PD1
+- #### laydate
+ - 优化 `theme` 属性,当其为数组格式,且第一个成员为 `hex` 格式主色值,则第二个成员为辅色值 # 1265
+- #### upload
+ - 新增 `exts` 属性对于图片类型时的 `.svg` 扩展名支持
+- #### code
+ - 优化 `copy` 属性开启时, 对 `tools` 属性的初始化配置 # I72QGO
+ - 优化 `preview: 'iframe'` 时的 `