release v2.8.9

release v2.8.9
pull/1304/head v2.8.9
贤心 2023-07-03 08:27:44 +08:00 committed by GitHub
commit 40277a7964
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 414 additions and 166 deletions

2
dist/css/layui.css vendored

File diff suppressed because one or more lines are too long

2
dist/layui.js vendored

File diff suppressed because one or more lines are too long

View File

@ -48,13 +48,13 @@
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<div class="layui-inline"> <div class="layui-inline">
<label class="layui-form-label">范围</label> <label class="layui-form-label">数字输入框</label>
<div class="layui-input-inline" style="width: 100px;"> <div class="layui-input-inline" style="width: 100px;">
<input type="text" name="price_min" placeholder="" autocomplete="off" class="layui-input"> <input type="number" name="price_min" placeholder="" autocomplete="off" class="layui-input" min="0" step="1" lay-affix="number">
</div> </div>
<div class="layui-form-mid">-</div> <div class="layui-form-mid">-</div>
<div class="layui-input-inline" style="width: 100px;"> <div class="layui-input-inline" style="width: 100px;">
<input type="text" name="price_max" placeholder="" autocomplete="off" class="layui-input"> <input type="number" name="price_max" placeholder="" autocomplete="off" class="layui-input" min="0" step="1" lay-affix="number">
</div> </div>
</div> </div>
</div> </div>

View File

@ -100,31 +100,51 @@ toc: true
<h2 id="affix" lay-toc="{hot: true}">动态点缀 <sup>2.8+</sup></h2> <h2 id="affix" lay-toc="{hot: true}">动态点缀 <sup>2.8+</sup></h2>
该功能允许对输入框内容进行相关动态操作。通过对输入框元素设置 `lay-affix` 属性来开启动态点缀,且输入框元素必须放置在一个具有输入框点缀结构的容器中(上文有讲解)如: 该功能允许对输入框内容进行相关动态操作。通过对输入框元素设置 `lay-affix` 属性来开启动态点缀。
``` | 点缀 | 属性值 |
input 放在前后置容器中:
<div class="layui-input-group">
<input type="text" lay-affix="clear">
</div>
input 放在前后缀容器中:
<div class="layui-input-wrap">
<input type="text" lay-affix="clear">
</div>
```
`lay-affix` 属性支持设置内置属性值和自定义值
| 值 | 描述 |
| --- | --- | | --- | --- |
| `lay-affix="eye"` | 密码框显隐 | | [数字输入框](#affix-number) <sup>2.8.9+</sup> | `lay-affix="number"` |
| `lay-affix="clear"` | 内容清除 | | [密码框显隐](#affix-eye) | `lay-affix="eye"` |
| `lay-affix="自定义图标值"` | 值对应图标类`layui-icon-`后面的名称([#详见图标列表](../icon/#list))。<br>可通过「[点缀事件](#affix-event)」完成自定义操作 | | [内容清除](#affix-clear) | `lay-affix="clear"` |
| [自定义动态点缀](#affix-custom) | `lay-affix="customName"` |
<h3 id="affix-number" lay-toc="{level: 2, hot: true}" class="ws-bold">
数字输入框 <sup>2.8.9+</sup>
</h3>
一般搭配 `<input type="number">` 使用,用于替代原生输入框,可继承 `step,min,max` 等原生属性。
<pre class="layui-code" lay-options="{preview: true, layout: ['preview', 'code'], done: function(obj){
obj.render();
}}">
<textarea>
<div class="layui-form">
<input type="number" lay-affix="number" placeholder="" value="0" class="layui-input">
<hr class="ws-space-16">
<div class="layui-row layui-col-space16">
<div class="layui-col-xs6">
<input type="number" lay-affix="number" placeholder="设置 step 为 0.01" step="0.01" class="layui-input">
</div>
<div class="layui-col-xs6">
<input type="number" lay-affix="number" placeholder="设置 step,min,max" step="10" min="0" max="100" class="layui-input">
</div>
<div class="layui-col-xs12">
<input type="number" lay-affix="number" disabled placeholder="禁用状态" value="0" class="layui-input">
</div>
</div>
</div>
<!-- import layui -->
</textarea>
</pre>
<h3 id="affix-eye" lay-toc="{level: 2}" class="ws-bold">密码显隐</h3> <h3 id="affix-eye" lay-toc="{level: 2}" class="ws-bold">密码显隐</h3>
一般搭配 `<input type="password">` 使用,用于控制输入框内容的显示和隐藏。
<pre class="layui-code" lay-options="{preview: true, layout: ['preview', 'code'], done: function(obj){ <pre class="layui-code" lay-options="{preview: true, layout: ['preview', 'code'], done: function(obj){
obj.render(); obj.render();
}}"> }}">
@ -141,6 +161,8 @@ input 放在前后缀容器中:
<h3 id="affix-clear" lay-toc="{level: 2}" class="ws-bold">内容清除</h3> <h3 id="affix-clear" lay-toc="{level: 2}" class="ws-bold">内容清除</h3>
一般搭配 `<input type="text">` 使用,用于清除输入框的内容。
<pre class="layui-code" lay-options="{preview: true, layout: ['preview', 'code'], done: function(obj){ <pre class="layui-code" lay-options="{preview: true, layout: ['preview', 'code'], done: function(obj){
obj.render(); obj.render();
}}"> }}">
@ -169,7 +191,7 @@ input 放在前后缀容器中:
<h3 id="affix-custom" lay-toc="{level: 2}" class="ws-bold">自定义动态点缀</h3> <h3 id="affix-custom" lay-toc="{level: 2}" class="ws-bold">自定义动态点缀</h3>
我们还可以对 `lay-affix` 属性设置任意图标值,从而实现自定义动态点缀功能。 我们还可以对 `lay-affix` 属性设置任意图标值,从而实现自定义动态点缀功能。 其中 `lay-affix="customName"` 值对应图标类`layui-icon-`后面的名称([#详见图标列表](../icon/#list))。且可通过「[点缀事件](#affix-event)」完成自定义操作。
<pre class="layui-code" lay-options="{preview: true, layout: ['preview', 'code'], done: function(obj){ <pre class="layui-code" lay-options="{preview: true, layout: ['preview', 'code'], done: function(obj){
obj.render(); obj.render();
@ -195,6 +217,7 @@ input 放在前后缀容器中:
form.on('input-affix(filter)', function(data){ form.on('input-affix(filter)', function(data){
var elem = data.elem; // 获取输入框 DOM 对象 var elem = data.elem; // 获取输入框 DOM 对象
var affix = data.affix; // 获取输入框 lay-affix 属性值 var affix = data.affix; // 获取输入框 lay-affix 属性值
console.log(this); // 当前触发点缀事件的图标元素
}); });
``` ```

View File

@ -149,6 +149,6 @@ layui.use(['element', 'layer', 'util'], function(){
> 小贴士:以上是一个基础的框体布局方案,若要实现诸如 `iframe` 跳转、侧边菜单收缩等功能,还需按照实际的业务需求自主实现。当然,也可以采用社区已有的 AdminUI 主题方案layuiAdmin 等。 > 小贴士:以上是一个基础的框体布局方案,若要实现诸如 `iframe` 跳转、侧边菜单收缩等功能,还需按照实际的业务需求自主实现。当然,也可以采用社区已有的 AdminUI 主题方案layuiAdmin 等。
<h2 id="adminui" lay-toc="">Admin UI</h2> <h2 id="adminui" lay-toc="{}">Admin UI</h2>
<a href="https://dev.layuion.com/themes/layuiadmin/" target="_blank">layuiAdmin</a> 是一套用于开发通用型管理系统的纯静态的 `HTML` 网页界面主题,基于开源的 Layui Web 组件库制作而成,没有任何后端程序及数据库存储等服务端代码。开发者使用该网页模板,可省去前端的大量工作,从而更高效地开发 Web 应用系统。 <a href="https://dev.layuion.com/themes/layuiadmin/" target="_blank">layuiAdmin</a> 是一套用于开发通用型管理系统的纯静态的 `HTML` 网页界面主题,基于开源的 Layui Web 组件库制作而成,没有任何后端程序及数据库存储等服务端代码。开发者使用该网页模板,可省去前端的大量工作,从而更高效地开发 Web 应用系统。

View File

@ -136,7 +136,7 @@ treeTable.render({
``` ```
treeTable.render({ treeTable.render({
elem: '', elem: '',
treee: { tree: {
enable: true, enable: true,
async: { async: {
format: function(trData, options, callback){ format: function(trData, options, callback){

View File

@ -265,6 +265,33 @@ acceptMime: 'image/jpeg, image/png` // 只筛选 jpg,png 格式图片
`true` `true`
</td>
</tr>
<tr>
<td>
[text](#options.text) <sup>2.8.9+</sup>
</td>
<td colspan="4">
<div id="options.text" lay-pid="options" class="ws-anchor">
自定义内部各类场景下的提示文本
</div>
```
text: { // 自定义提示文本
"data-format-error": "", // 数据格式错误的提示
"check-error": "", // 文件格式校验失败的提示
"error": "", // 上传失败的提示
"limit-number": null, // 限制 number 属性的提示。若设置,需为函数写法
"limit-size": null, // 限制 size 属性的提示。若设置,需为函数写法
"cross-domain": "", // IE 下跨域的提示
}
```
</td> </td>
</tr> </tr>
<tr> <tr>

View File

@ -1,4 +1,4 @@
<pre class="layui-code" lay-options="{preview: true, codeStyle: 'height: 535px;', layout: ['preview', 'code'], tools: ['full']}"> <pre class="layui-code" lay-options="{preview: true, codeStyle: 'height: 535px;', layout: ['preview', 'code'], allowParse: true, tools: ['full']}">
<textarea> <textarea>
<h3 class="ws-anchor ws-bold">倒计时</h3> <h3 class="ws-anchor ws-bold">倒计时</h3>
@ -6,11 +6,8 @@
<div class="layui-inline"> <div class="layui-inline">
<input type="text" readonly class="layui-input" id="test1" value="2099-12-31 00:00:00"> <input type="text" readonly class="layui-input" id="test1" value="2099-12-31 00:00:00">
</div> </div>
<span class="layui-word-aux layui-font-green" id="test2"></span>
<blockquote class="layui-elem-quote" style="margin-top: 10px;">
<div id="test2"></div>
</blockquote>
<h3 class="ws-anchor ws-bold">某个时间在多久前</h3> <h3 class="ws-anchor ws-bold">某个时间在多久前</h3>
请选择要计算的日期: 请选择要计算的日期:
@ -51,26 +48,29 @@ layui.use(function(){
var $ = layui.$; var $ = layui.$;
// 倒计时 // 倒计时
var thisTimer; var countdown = util.countdown({
var setCountdown = function(value){ date: '2099-12-31 00:00:00', // 目标时间值
var endTime = new Date(value); // 结束日期 now: new Date(), // 当前时间,一般为服务器时间,此处以本地时间为例
var serverTime = new Date(); // 假设为当前服务器时间,这里采用的是本地时间,实际使用一般是取服务端的 ready: function(){ // 初始操作
clearTimeout(util.countdown.timer); // 清除旧定时器,防止多次渲染时重复执行。实际使用时不常用
clearTimeout(thisTimer); },
util.countdown(endTime, serverTime, function(date, serverTime, timer){ clock: function(obj, inst){ // 计时中
var str = date[0] + ' 天 ' + date[1] + ' 时 ' + date[2] + ' 分 ' + date[3] + ' 秒'; var str = [obj.d,'天',obj.h,'时',obj.m,'分',obj.s,'秒'].join(' ');
lay('#test2').html('距离上述日期还有:'+ str); lay('#test2').html(str);
thisTimer = timer; util.countdown.timer = inst.timer; // 记录当前定时器,以便在重复渲染时清除。实际使用时不常用
}); },
}; done: function(obj, inst){ // 计时完成
layer.msg('Time is up');
setCountdown('2099-12-31 00:00:00'); }
});
// 重置倒计时
laydate.render({ laydate.render({
elem: '#test1', elem: '#test1',
type: 'datetime', type: 'datetime',
done: function(value, date){ done: function(value){
setCountdown(value); countdown.reload({
date: value
});
} }
}); });
@ -125,4 +125,4 @@ layui.use(function(){
}); });
</script> </script>
</textarea> </textarea>
</pre> </pre>

View File

@ -20,8 +20,8 @@ toc: true
| API | 描述 | | API | 描述 |
| --- | --- | | --- | --- |
| var util = layui.util | 获得 `util` 模块。 | | var util = layui.util | 获得 `util` 模块。 |
| util.fixbar(options) | `fixbar` 固定条组件,用法:[#详见](../fixbar/) | | [util.fixbar(options)](../fixbar/) | 固定条组件 |
| [util.countdown(endTime, serverTime, callback)](#countdown) | 倒计时 | | [util.countdown(options)](#countdown) | 倒计时组件 |
| [util.timeAgo(time, onlyDate)](#timeAgo) | 某个时间在多久前 | | [util.timeAgo(time, onlyDate)](#timeAgo) | 某个时间在多久前 |
| [util.toDateString(time, format)](#toDateString) | 将毫秒数或日期对象转换成日期格式字符 | | [util.toDateString(time, format)](#toDateString) | 将毫秒数或日期对象转换成日期格式字符 |
| [util.digit(num, length)](#digit) | 数字前置补零 | | [util.digit(num, length)](#digit) | 数字前置补零 |
@ -32,26 +32,45 @@ toc: true
<h3 id="countdown" class="ws-anchor ws-bold">倒计时</h3> <h3 id="countdown" class="ws-anchor ws-bold">倒计时</h3>
`util.countdown(endTime, serverTime, callback);` `util.countdown(options);`
- 参数 `endTime` : 结束时间毫秒数或 `Date` 对象 - 参数 `options` <sup>2.8.9+</sup>: 属性配置项。可选项详见下表:
- 参数 `serverTime` : 服务器当前时间毫秒数 或 `Date` 对象
- 参数 `callback` : 倒计时回调函数。若倒计时正在运行,则每一秒都会执行一次。并且返回以下三个参数。
- `date` 包含天/时/分/秒的对象
- `serverTime` 当前服务器时间毫秒数或 `Date` 对象
- `timer` 计时器返回的索引,用于 `clearTimeout`
该方法并不负责视图的呈现,而仅返回倒计时数值。 相关用法见:[#示例](#examples) | 属性 | 描述 |
| --- | --- |
| date | 目标时间值。值可以为毫秒数或 `Date` 对象 |
| now | 当前时间值,一般为当前服务器时间。值可以为毫秒数或 `Date` 对象 |
| ready | 倒计时初始时的回调函数。 |
| clock | 倒计时计时中的回调函数,每秒触发一次,直到计时完成。 |
| done | 倒计时计时完成的回调函数,即到达目标时间值时触发 |
- 注: <sup>2.8.9</sup> 之前的版本写法为:`util.countdown(date, now, clock);`
该方法返回的实例对象成员如下 <sup>2.8.9+</sup>
```js
var countdown = util.countdown(options);
countdown.clear(); // 清除当前倒计时
countdown.reload(options); // 重载当前倒计时。
countdown.timer; // 当前倒计时计时器 ID
``` ```
相关用法可参考:[#示例](#examples)
```js
layui.use('util', function(){ layui.use('util', function(){
var util = layui.util; var util = layui.util;
// 示例 // 示例
var endTime = new Date(2099,1,1).getTime() // 假设为结束日期 util.countdown({
var serverTime = new Date().getTime(); // 这里采用的是本地时间,实际使用一般是取服务端时间 date: '2099-1-1', // 目标时间值
now: new Date(), // 当前时间,一般为服务器时间,此处以本地时间为例
util.countdown(endTime, serverTime, function(date, serverTime, timer){ clock: function(obj, countdown){ // 计时中
console.log(date, serverTime, timer) console.log(obj); // 得到当前计时器的「天、时、分、秒」值
console.log(countdown); // 得到当前实例对象
},
done: function(obj, countdown){ // 计时完成
console.log('time is up');
}
}); });
}); });
``` ```

View File

@ -12,6 +12,29 @@ toc: true
> 导读:📑 [Layui 2.8 《升级指南》](/notes/2.8/upgrade-guide.html) · 📑 [Layui 新版文档站上线初衷](/notes/2.8/news.html) > 导读:📑 [Layui 2.8 《升级指南》](/notes/2.8/upgrade-guide.html) · 📑 [Layui 新版文档站上线初衷](/notes/2.8/news.html)
<h2 id="2.8.9" class="ws-anchor">
2.8.9
<span class="layui-badge-rim">2023-07-03</span>
</h2>
- #### 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)
---
<h2 id="2.8.8" class="ws-anchor"> <h2 id="2.8.8" class="ws-anchor">
2.8.8 2.8.8
<span class="layui-badge-rim">2023-06-20</span> <span class="layui-badge-rim">2023-06-20</span>

View File

@ -23,7 +23,7 @@
<div class="layui-input-split layui-input-prefix"> <div class="layui-input-split layui-input-prefix">
前置信息 前置信息
</div> </div>
<input type="text" name="arr[]" required lay-verify="required" placeholder="请输入" autocomplete="off" class="layui-input"> <input type="text" name="arr[]" required lay-verify="required" placeholder="请输入" autocomplete="off" class="layui-input" lay-affix="clear">
<div class="layui-input-split layui-input-suffix"> <div class="layui-input-split layui-input-suffix">
后置信息 后置信息
</div> </div>
@ -109,6 +109,26 @@
</select> </select>
</div> </div>
</div> </div>
<div class="layui-col-md3">
<div class="layui-input-wrap">
<div class="layui-input-prefix">
<i class="layui-icon layui-icon-date"></i>
</div>
<input type="text" name="arr[]" required placeholder="前缀和后缀+动态点缀" autocomplete="off" class="layui-input" lay-affix="clear">
<div class="layui-input-suffix">
<i class="layui-icon layui-icon-down"></i>
</div>
</div>
</div>
<div class="layui-col-md3">
<input type="number" step="0.01" min="0" max="10" name="arr[]" required placeholder="数字输入框" lay-affix="number" autocomplete="off" class="layui-input">
</div>
<div class="layui-col-md3">
<input type="number" step="0.01" min="0" max="10" name="arr[]" required placeholder="系统自带数字输入框" autocomplete="off" class="layui-input">
</div>
<div class="layui-col-md3">
<input type="number" disabled name="arr[]" required placeholder="数字输入框 禁用状态" lay-affix="number" autocomplete="off" class="layui-input">
</div>
<div class="layui-col-md12"> <div class="layui-col-md12">
<div class="layui-input-wrap"> <div class="layui-input-wrap">
<textarea class="layui-textarea" lay-affix="clear"></textarea> <textarea class="layui-textarea" lay-affix="clear"></textarea>

View File

@ -55,7 +55,7 @@
</script> </script>
<script type="text/html" id="cityTpl"> <script type="text/html" id="cityTpl">
<select id="demoCity1" lay-ignore> <select id="demoCity1" lay-unrow lay-ignore>
<option value="浙江杭州">浙江杭州</option> <option value="浙江杭州">浙江杭州</option>
<option value="江西南昌">江西南昌</option> <option value="江西南昌">江西南昌</option>
<option value="湖北武汉">湖北武汉</option> <option value="湖北武汉">湖北武汉</option>

View File

@ -24,6 +24,7 @@ layui.use(['treeTable'], function(){
url: './json/treeTable/demo-1.json', url: './json/treeTable/demo-1.json',
maxHeight: 'full-32', maxHeight: 'full-32',
cols: [[ cols: [[
{type: 'checkbox', fixed: 'left'},
{type: 'numbers', fixed: 'left'}, {type: 'numbers', fixed: 'left'},
{field: 'id', title: 'ID', width: 145, sort: true, fixed: 'left', totalRow: '合计:'}, {field: 'id', title: 'ID', width: 145, sort: true, fixed: 'left', totalRow: '合计:'},
{field: 'name', title: '用户名', width: 180, fixed: 'left'}, {field: 'name', title: '用户名', width: 180, fixed: 'left'},

View File

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

View File

@ -722,6 +722,7 @@ a cite{font-style: normal; *cursor:pointer;}
.layui-input:hover, .layui-textarea:hover{border-color: #d2d2d2 !important;} .layui-input:hover, .layui-textarea:hover{border-color: #d2d2d2 !important;}
.layui-input:focus, .layui-textarea:focus{border-color: #16b777 !important; box-shadow: 0 0 0 3px rgba(22,183,119,0.08);} .layui-input:focus, .layui-textarea:focus{border-color: #16b777 !important; box-shadow: 0 0 0 3px rgba(22,183,119,0.08);}
.layui-textarea{position: relative; min-height: 100px; height: auto; line-height: 20px; padding: 6px 10px; resize: vertical;} .layui-textarea{position: relative; min-height: 100px; height: auto; line-height: 20px; padding: 6px 10px; resize: vertical;}
.layui-input[disabled], .layui-textarea[disabled]{background-color: #fafafa;}
.layui-select{padding: 0 10px;} .layui-select{padding: 0 10px;}
.layui-form select, .layui-form select,
.layui-form input[type=checkbox], .layui-form input[type=checkbox],
@ -780,6 +781,7 @@ a cite{font-style: normal; *cursor:pointer;}
.layui-input-wrap .layui-input-prefix, .layui-input-wrap .layui-input-prefix,
.layui-input-wrap .layui-input-suffix, .layui-input-wrap .layui-input-suffix,
.layui-input-wrap .layui-input-split{pointer-events: none;} .layui-input-wrap .layui-input-split{pointer-events: none;}
.layui-input-wrap .layui-input:hover + .layui-input-split{border-color: #d2d2d2;}
.layui-input-wrap .layui-input:focus + .layui-input-split{border-color: #16b777;} .layui-input-wrap .layui-input:focus + .layui-input-split{border-color: #16b777;}
.layui-input-wrap .layui-input-prefix.layui-input-split{border-width: 0; border-right-width: 1px;} .layui-input-wrap .layui-input-prefix.layui-input-split{border-width: 0; border-right-width: 1px;}
@ -790,6 +792,17 @@ a cite{font-style: normal; *cursor:pointer;}
.layui-input-affix .layui-icon-clear{color: rgba(0,0,0,.3);} .layui-input-affix .layui-icon-clear{color: rgba(0,0,0,.3);}
.layui-input-affix .layui-icon:hover{color: rgba(0,0,0,.6);} .layui-input-affix .layui-icon:hover{color: rgba(0,0,0,.6);}
/* 数字输入框动态点缀 */
.layui-input-number{width: 24px; padding: 0;}
.layui-input-number .layui-icon{position: absolute; right: 0; width: 100%; height: 50%; line-height: normal; font-size: 12px;}
.layui-input-number .layui-icon:before{position: absolute; left: 50%; top: 50%; margin-top: -6px; margin-left: -6px;}
.layui-input-number .layui-icon:first-child{top: 0; border-bottom: 1px solid #eee;}
.layui-input-number .layui-icon:last-child{bottom: 0;}
.layui-input-number .layui-icon:hover{font-weight: 700;}
.layui-input-wrap .layui-input[type="number"]::-webkit-outer-spin-button,
.layui-input-wrap .layui-input[type="number"]::-webkit-inner-spin-button{-webkit-appearance: none !important;}
.layui-input-wrap .layui-input[type="number"]{-moz-appearance: textfield;}
/* 下拉选择 */ /* 下拉选择 */
@ -822,6 +835,7 @@ a cite{font-style: normal; *cursor:pointer;}
.layui-form-checkbox:hover{} .layui-form-checkbox:hover{}
.layui-form-checkbox > *{display: inline-block; vertical-align: middle;} .layui-form-checkbox > *{display: inline-block; vertical-align: middle;}
.layui-form-checkbox > div{padding: 0 11px; font-size: 14px; border-radius: 2px 0 0 2px; background-color: #d2d2d2; color: #fff; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;} .layui-form-checkbox > div{padding: 0 11px; font-size: 14px; border-radius: 2px 0 0 2px; background-color: #d2d2d2; color: #fff; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;}
.layui-form-checkbox > div > .layui-icon{line-height: normal}
.layui-form-checkbox:hover > div{background-color: #c2c2c2;} .layui-form-checkbox:hover > div{background-color: #c2c2c2;}
.layui-form-checkbox > i{position: absolute; right: 0; top: 0; width: 30px; height: 100%; border: 1px solid #d2d2d2; border-left: none; border-radius: 0 2px 2px 0; color: #fff; color: rgba(255,255,255,0); font-size: 20px; text-align: center; box-sizing: border-box;} .layui-form-checkbox > i{position: absolute; right: 0; top: 0; width: 30px; height: 100%; border: 1px solid #d2d2d2; border-left: none; border-radius: 0 2px 2px 0; color: #fff; color: rgba(255,255,255,0); font-size: 20px; text-align: center; box-sizing: border-box;}
.layui-form-checkbox:hover > i{border-color: #c2c2c2; color: #c2c2c2;} .layui-form-checkbox:hover > i{border-color: #c2c2c2; color: #c2c2c2;}
@ -1509,12 +1523,12 @@ body .layui-util-face .layui-layer-content{padding:0; background-color:#fff; co
.layui-slider-wrap-btn.layui-disabled:hover{transform: scale(1) !important;} .layui-slider-wrap-btn.layui-disabled:hover{transform: scale(1) !important;}
.layui-slider-tips{position: absolute; top: -42px; z-index: 77777777; white-space:nowrap; display: none; -webkit-transform: translateX(-50%); transform: translateX(-50%); color: #FFF; background: #000; border-radius: 3px; height: 25px; line-height: 25px; padding: 0 10px;} .layui-slider-tips{position: absolute; top: -42px; z-index: 77777777; white-space:nowrap; display: none; -webkit-transform: translateX(-50%); transform: translateX(-50%); color: #FFF; background: #000; border-radius: 3px; height: 25px; line-height: 25px; padding: 0 10px;}
.layui-slider-tips:after{content: ""; position: absolute; bottom: -12px; left: 50%; margin-left: -6px; width: 0; height: 0; border-width: 6px; border-style: solid; border-color: #000 transparent transparent transparent;} .layui-slider-tips:after{content: ""; position: absolute; bottom: -12px; left: 50%; margin-left: -6px; width: 0; height: 0; border-width: 6px; border-style: solid; border-color: #000 transparent transparent transparent;}
.layui-slider-input{width: 70px; height: 32px; border: 1px solid #eee; border-radius: 3px; font-size: 16px; line-height: 32px; position: absolute; right: 0; top: -14px;} .layui-slider-input{width: 70px; height: 32px; border: 1px solid #eee; border-radius: 3px; font-size: 16px; line-height: 32px; position: absolute; right: 0; top: -14px; box-sizing: border-box;}
.layui-slider-input-btn{position: absolute; top: 0; right: 0; width: 20px; height: 100%; border-left: 1px solid #eee;} .layui-slider-input-btn{position: absolute; top: 0; right: 0; width: 20px; height: 100%; border-left: 1px solid #eee;}
.layui-slider-input-btn i{cursor: pointer; position: absolute; right: 0; bottom: 0; width: 20px; height: 50%; font-size: 12px; line-height: 16px; text-align: center; color: #999;} .layui-slider-input-btn i{cursor: pointer; position: absolute; right: 0; bottom: 0; width: 20px; height: 50%; font-size: 12px; line-height: 16px; text-align: center; color: #999;}
.layui-slider-input-btn i:first-child{top: 0; border-bottom: 1px solid #eee;} .layui-slider-input-btn i:first-child{top: 0; border-bottom: 1px solid #eee;}
.layui-slider-input-txt{height: 100%; font-size: 14px;} .layui-slider-input-txt{height: 100%; font-size: 14px;}
.layui-slider-input-txt input{height: 100%; border: none;} .layui-slider-input-txt input{height: 100%; border: none; padding-right: 21px;}
.layui-slider-input-btn i:hover{color: #16baaa;} .layui-slider-input-btn i:hover{color: #16baaa;}
/*垂直滑块*/ /*垂直滑块*/
.layui-slider-vertical{width: 4px; margin-left: 33px;} .layui-slider-vertical{width: 4px; margin-left: 33px;}

View File

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

View File

@ -90,6 +90,14 @@ layui.define(['lay', 'util', 'element', 'form'], function(exports){
othis.data('code', codes); othis.data('code', codes);
// code
var html = finalCode = codes.join('');
// 外部重新解析 code
if(typeof options.codeParse === 'function'){
html = finalCode = options.codeParse(html);
}
// 工具栏 // 工具栏
var tools = { var tools = {
copy: { copy: {
@ -231,7 +239,7 @@ layui.define(['lay', 'util', 'element', 'form'], function(exports){
var run = function(thisItemBody){ var run = function(thisItemBody){
var iframe = thisItemBody.children('iframe')[0]; var iframe = thisItemBody.children('iframe')[0];
if(isIframePreview && iframe){ if(isIframePreview && iframe){
iframe.srcdoc = codes.join(''); iframe.srcdoc = finalCode;
} else { } else {
thisItemBody.html(codes.join('')); thisItemBody.html(codes.join(''));
} }
@ -297,13 +305,7 @@ layui.define(['lay', 'util', 'element', 'form'], function(exports){
} }
// code
var html = finalCode = codes.join('');
// 外部重新解析 code
if(typeof options.codeParse === 'function'){
html = finalCode = options.codeParse(html);
}
// 转义 HTML 标签 // 转义 HTML 标签
if(options.encode) html = util.escape(html); // 编码 if(options.encode) html = util.escape(html); // 编码

View File

@ -162,6 +162,7 @@ layui.define(['lay', 'layer', 'util'], function(exports){
elemForm.find('input[lay-affix],textarea[lay-affix]').each(function(){ elemForm.find('input[lay-affix],textarea[lay-affix]').each(function(){
var othis = $(this); var othis = $(this);
var affix = othis.attr('lay-affix'); var affix = othis.attr('lay-affix');
var CLASS_WRAP = 'layui-input-wrap';
var CLASS_SUFFIX = 'layui-input-suffix'; var CLASS_SUFFIX = 'layui-input-suffix';
var CLASS_AFFIX = 'layui-input-affix'; var CLASS_AFFIX = 'layui-input-affix';
var disabled = othis.is('[disabled]') || othis.is('[readonly]'); var disabled = othis.is('[disabled]') || othis.is('[readonly]');
@ -179,17 +180,32 @@ layui.define(['lay', 'layer', 'util'], function(exports){
value: affix value: affix
}), opts, lay.options(othis[0])); }), opts, lay.options(othis[0]));
var elemAffix = $('<div class="'+ CLASS_AFFIX +'">'); var elemAffix = $('<div class="'+ CLASS_AFFIX +'">');
var elemIcon = $('<i class="layui-icon layui-icon-'+ opts.value + ( var value = layui.isArray(opts.value) ? opts.value : [opts.value];
opts.disabled ? (' '+ DISABLED) : '' var elemIcon = $(function(){
) +'"></i>'); var arr = [];
layui.each(value, function(i, item){
arr.push('<i class="layui-icon layui-icon-'+ item + (
opts.disabled ? (' '+ DISABLED) : ''
) +'"></i>');
});
return arr.join('');
}());
elemAffix.append(elemIcon); elemAffix.append(elemIcon); // 插入图标元素
// 追加 className
if(opts.split) elemAffix.addClass('layui-input-split'); if(opts.split) elemAffix.addClass('layui-input-split');
if(opts.className) elemAffix.addClass(opts.className);
// 移除旧的元素 // 移除旧的元素
var hasElemAffix = othis.next('.'+ CLASS_AFFIX); var hasElemAffix = othis.next('.'+ CLASS_AFFIX);
if(hasElemAffix[0]) hasElemAffix.remove(); if(hasElemAffix[0]) hasElemAffix.remove();
// 是否在规定的容器中
if(!othis.parent().hasClass(CLASS_WRAP)){
othis.wrap('<div class="'+ CLASS_WRAP +'"></div>');
}
// 是否已经存在后缀元素 // 是否已经存在后缀元素
var hasElemSuffix = othis.next('.'+ CLASS_SUFFIX); var hasElemSuffix = othis.next('.'+ CLASS_SUFFIX);
if(hasElemSuffix[0]){ if(hasElemSuffix[0]){
@ -256,6 +272,36 @@ layui.define(['lay', 'layer', 'util'], function(exports){
}, },
show: 'auto', // 根据输入框值是否存在来显示或隐藏点缀图标 show: 'auto', // 根据输入框值是否存在来显示或隐藏点缀图标
disabled: disabled // 跟随输入框禁用状态 disabled: disabled // 跟随输入框禁用状态
},
number: { // 数字输入框
value: ['up', 'down'],
split: true,
className: 'layui-input-number',
disabled: disabled, // 跟随输入框禁用状态
click: function(elem){
var index = $(this).index();
var value = elem.val();
var step = Number(elem.attr('step')) || 1; // 加减的数字间隔
var min = Number(elem.attr('min'));
var max = Number(elem.attr('max'));
if(isNaN(value)) return; // 若非数字,则不作处理
value = Number(value);
value = index ? value - step : value + step;
// min max
if(value < min) value = min;
if(value > max) value = max;
// 小数点后保留位数
var fixed = function(step){
return (step.match(/(?<=\.)[\d]+$/) || [''])[0].length;
}(step.toString());
if(fixed) value = value.toFixed(fixed);
elem.val(value);
}
} }
}; };

View File

@ -179,7 +179,7 @@ layui.define(['jquery', 'lay'], function(exports){
//插入输入框 //插入输入框
if(options.input && !options.range){ if(options.input && !options.range){
var elemInput = $('<div class="layui-slider-input layui-input"><div class="layui-slider-input-txt"><input type="text" class="layui-input"></div><div class="layui-slider-input-btn"><i class="layui-icon layui-icon-up"></i><i class="layui-icon layui-icon-down"></i></div></div>'); var elemInput = $('<div class="layui-slider-input"><div class="layui-slider-input-txt"><input type="text" class="layui-input"></div><div class="layui-slider-input-btn"><i class="layui-icon layui-icon-up"></i><i class="layui-icon layui-icon-down"></i></div></div>');
othis.css("position","relative"); othis.css("position","relative");
othis.append(elemInput); othis.append(elemInput);
othis.find('.' + SLIDER_INPUT_TXT).children('input').val(options.value); othis.find('.' + SLIDER_INPUT_TXT).children('input').val(options.value);

View File

@ -2314,9 +2314,9 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
// 显示编辑表单 // 显示编辑表单
if(editType){ if(editType){
var input = $(function(){ var input = $(function(){
var inputElem = '<input class="layui-input '+ ELEM_EDIT +'">'; var inputElem = '<input class="layui-input '+ ELEM_EDIT +'" lay-unrow>';
if(editType === 'textarea') { if(editType === 'textarea') {
inputElem = '<textarea class="layui-input ' + ELEM_EDIT + '"></textarea>'; inputElem = '<textarea class="layui-input ' + ELEM_EDIT + '" lay-unrow></textarea>';
} }
return inputElem; return inputElem;
}()); }());

View File

@ -68,6 +68,7 @@ layui.define(['table'], function (exports) {
var ELEM_FIXED = '.layui-table-fixed'; var ELEM_FIXED = '.layui-table-fixed';
var ELEM_FIXL = '.layui-table-fixed-l'; var ELEM_FIXL = '.layui-table-fixed-l';
var ELEM_FIXR = '.layui-table-fixed-r'; var ELEM_FIXR = '.layui-table-fixed-r';
var ELEM_CHECKED = 'layui-table-checked';
var TABLE_TREE = 'layui-table-tree'; var TABLE_TREE = 'layui-table-tree';
var LAY_DATA_INDEX = 'LAY_DATA_INDEX'; var LAY_DATA_INDEX = 'LAY_DATA_INDEX';
@ -1511,8 +1512,15 @@ layui.define(['table'], function (exports) {
if (dataP) { if (dataP) {
var trsP = that.updateParentCheckStatus(dataP, layui.type(checked) === 'boolean' ? checked : null); var trsP = that.updateParentCheckStatus(dataP, layui.type(checked) === 'boolean' ? checked : null);
layui.each(trsP, function (indexP, itemP) { layui.each(trsP, function (indexP, itemP) {
form.render(tableView.find('tr[lay-data-index="' + itemP[LAY_DATA_INDEX] + '"] input[name="layTableCheckbox"]:not(:disabled)').prop({ var checkboxElem = tableView.find('tr[lay-data-index="' + itemP[LAY_DATA_INDEX] + '"] input[name="layTableCheckbox"]:not(:disabled)');
checked: itemP[checkName], var checked = itemP[checkName];
// 标记父节点行背景色
checkboxElem.closest('tr')[checked ? 'addClass' : 'removeClass'](ELEM_CHECKED);
// 设置原始复选框 checked 属性值并渲染
form.render(checkboxElem.prop({
checked: checked,
indeterminate: itemP[LAY_CHECKBOX_HALF] indeterminate: itemP[LAY_CHECKBOX_HALF]
})) }))
}) })
@ -1639,11 +1647,15 @@ layui.define(['table'], function (exports) {
// that.updateStatus(null, statusChecked); // 取消其他的选中状态 // that.updateStatus(null, statusChecked); // 取消其他的选中状态
that.updateStatus(null, function (d) { that.updateStatus(null, function (d) {
if (d[checkName]) { if (d[checkName]) {
var radioElem = tableView.find('tr[lay-data-index="' + d[LAY_DATA_INDEX] + '"] input[type="radio"][lay-type="layTableRadio"]');
d[checkName] = false; d[checkName] = false;
form.render(tableView.find('tr[lay-data-index="' + d[LAY_DATA_INDEX] + '"] input[type="radio"][lay-type="layTableRadio"]').prop('checked', false)); radioElem.closest('tr').removeClass(ELEM_CHECKED); // 取消当前选中行背景色
form.render(radioElem.prop('checked', false));
} }
}); // 取消其他的选中状态 }); // 取消其他的选中状态
trData[checkName] = checked; trData[checkName] = checked;
trElem[checked ? 'addClass' : 'removeClass'](ELEM_CHECKED); // 标记当前选中行背景色
trElem.siblings().removeClass(ELEM_CHECKED); // 取消其他行背景色
form.render(trElem.find('input[type="radio"][lay-type="layTableRadio"]').prop('checked', checked)); form.render(trElem.find('input[type="radio"][lay-type="layTableRadio"]').prop('checked', checked));
} else { } else {
var isParentKey = options.tree.customName.isParent; var isParentKey = options.tree.customName.isParent;
@ -1660,9 +1672,11 @@ layui.define(['table'], function (exports) {
} }
var trs = that.updateStatus(trData ? [trData] : table.cache[tableId], checkedStatusFn); var trs = that.updateStatus(trData ? [trData] : table.cache[tableId], checkedStatusFn);
form.render(tableView.find(trs.map(function (value) { var checkboxElem = tableView.find(trs.map(function (value) {
return 'tr[lay-data-index="' + value[LAY_DATA_INDEX] + '"] input[name="layTableCheckbox"]:not(:disabled)'; return 'tr[lay-data-index="' + value[LAY_DATA_INDEX] + '"] input[name="layTableCheckbox"]:not(:disabled)';
}).join(',')).prop({checked: checked, indeterminate: false})); }).join(','));
checkboxElem.closest('tr')[checked ? 'addClass' : 'removeClass'](ELEM_CHECKED); // 标记当前选中行背景色
form.render(checkboxElem.prop({checked: checked, indeterminate: false}));
// } // }
var trDataP; var trDataP;
// 更新父节点以及更上层节点的状态 // 更新父节点以及更上层节点的状态

View File

@ -53,7 +53,6 @@ layui.define(['lay','layer'], function(exports){
var ELEM_CHOOSE = 'layui-upload-choose'; var ELEM_CHOOSE = 'layui-upload-choose';
var ELEM_DRAG = 'layui-upload-drag'; var ELEM_DRAG = 'layui-upload-drag';
// 构造器 // 构造器
var Class = function(options){ var Class = function(options){
var that = this; var that = this;
@ -76,7 +75,15 @@ layui.define(['lay','layer'], function(exports){
drag: true, // 是否允许拖拽上传 drag: true, // 是否允许拖拽上传
size: 0, // 文件限制大小,默认不限制 size: 0, // 文件限制大小,默认不限制
number: 0, // 允许同时上传的文件数,默认不限制 number: 0, // 允许同时上传的文件数,默认不限制
multiple: false // 是否允许多文件上传不支持ie8-9 multiple: false, // 是否允许多文件上传,不支持 ie8-9
text: { // 自定义提示文本
"cross-domain": "Cross-domain requests are not supported", // 跨域
"data-format-error": "Please return JSON data format", // 数据格式错误
"check-error": "", // 文件格式校验失败
"error": "", // 上传失败
"limit-number": null, // 限制 number 属性的提示 --- function
"limit-size": null // 限制 size 属性的提示 --- function
}
}; };
// 初始渲染 // 初始渲染
@ -152,8 +159,8 @@ layui.define(['lay','layer'], function(exports){
//异常提示 //异常提示
Class.prototype.msg = function(content){ Class.prototype.msg = function(content){
return layer.msg(content, { return layer.msg(content, {
icon: 2 icon: 2,
,shift: 6 shift: 6
}); });
}; };
@ -182,6 +189,7 @@ layui.define(['lay','layer'], function(exports){
Class.prototype.upload = function(files, type){ Class.prototype.upload = function(files, type){
var that = this; var that = this;
var options = that.config; var options = that.config;
var text = options.text || {};
var elemFile = that.elemFile[0]; var elemFile = that.elemFile[0];
// 获取文件队列 // 获取文件队列
@ -237,7 +245,7 @@ layui.define(['lay','layer'], function(exports){
}, },
error: function(e){ // 异常回调 error: function(e){ // 异常回调
options.unified ? (failed += that.fileLength) : failed++; options.unified ? (failed += that.fileLength) : failed++;
that.msg([ that.msg(text['error'] || [
'Upload failed, please try again.', 'Upload failed, please try again.',
'status: '+ (e.status || '') +' - '+ (e.statusText || 'error') 'status: '+ (e.status || '') +' - '+ (e.statusText || 'error')
].join('<br>')); ].join('<br>'));
@ -284,14 +292,14 @@ layui.define(['lay','layer'], function(exports){
that.elemFile.parent().submit(); that.elemFile.parent().submit();
//获取响应信息 // 获取响应信息
clearInterval(Class.timer); clearInterval(Class.timer);
Class.timer = setInterval(function() { Class.timer = setInterval(function() {
var res, iframeBody = iframe.contents().find('body'); var res, iframeBody = iframe.contents().find('body');
try { try {
res = iframeBody.text(); res = iframeBody.text();
} catch(e) { } catch(e) {
that.msg('Cross-domain requests are not supported'); that.msg(text['cross-domain']);
clearInterval(Class.timer); clearInterval(Class.timer);
error(); error();
} }
@ -314,7 +322,7 @@ layui.define(['lay','layer'], function(exports){
res = JSON.parse(res); res = JSON.parse(res);
} catch(e){ } catch(e){
res = {}; res = {};
return that.msg('Please return JSON data format'); return that.msg(text['data-format-error']);
} }
} }
} }
@ -377,7 +385,7 @@ layui.define(['lay','layer'], function(exports){
// 上传前的回调 - 如果回调函数明确返回 false则停止上传 // 上传前的回调 - 如果回调函数明确返回 false则停止上传
if(options.before && (options.before(args) === false)) return; if(options.before && (options.before(args) === false)) return;
// IE兼容处理 // IE 兼容处理
if(device.ie){ if(device.ie){
return device.ie > 9 ? ajaxSend() : iframeSend(); return device.ie > 9 ? ajaxSend() : iframeSend();
} }
@ -393,37 +401,37 @@ layui.define(['lay','layer'], function(exports){
audio: '音频' audio: '音频'
})[options.accept] || '文件'; })[options.accept] || '文件';
//校验文件格式 // 校验文件格式
value = value.length === 0 value = value.length === 0
? ((elemFile.value.match(/[^\/\\]+\..+/g)||[]) || '') ? ((elemFile.value.match(/[^\/\\]+\..+/g)||[]) || '')
: value; : value;
if(value.length === 0) return; if(value.length === 0) return;
//根据文件类型校验 // 根据文件类型校验
switch(options.accept){ switch(options.accept){
case 'file': //一般文件 case 'file': // 一般文件
layui.each(value, function(i, item){ layui.each(value, function(i, item){
if(exts && !RegExp('.\\.('+ exts +')$', 'i').test(escape(item))){ if(exts && !RegExp('.\\.('+ exts +')$', 'i').test(escape(item))){
return check = true; return check = true;
} }
}); });
break; break;
case 'video': //视频文件 case 'video': // 视频文件
layui.each(value, function(i, item){ layui.each(value, function(i, item){
if(!RegExp('.\\.('+ (exts || 'avi|mp4|wma|rmvb|rm|flash|3gp|flv') +')$', 'i').test(escape(item))){ if(!RegExp('.\\.('+ (exts || 'avi|mp4|wma|rmvb|rm|flash|3gp|flv') +')$', 'i').test(escape(item))){
return check = true; return check = true;
} }
}); });
break; break;
case 'audio': //音频文件 case 'audio': // 音频文件
layui.each(value, function(i, item){ layui.each(value, function(i, item){
if(!RegExp('.\\.('+ (exts || 'mp3|wav|mid') +')$', 'i').test(escape(item))){ if(!RegExp('.\\.('+ (exts || 'mp3|wav|mid') +')$', 'i').test(escape(item))){
return check = true; return check = true;
} }
}); });
break; break;
default: //图片文件 default: // 图片文件
layui.each(value, function(i, item){ layui.each(value, function(i, item){
if(!RegExp('.\\.('+ (exts || 'jpg|png|gif|bmp|jpeg|svg') +')$', 'i').test(escape(item))){ if(!RegExp('.\\.('+ (exts || 'jpg|png|gif|bmp|jpeg|svg') +')$', 'i').test(escape(item))){
return check = true; return check = true;
@ -432,13 +440,13 @@ layui.define(['lay','layer'], function(exports){
break; break;
} }
//校验失败提示 // 校验失败提示
if(check){ if(check){
that.msg('选择的'+ typeName +'中包含不支持的格式'); that.msg(text['check-error'] || ('选择的'+ typeName +'中包含不支持的格式'));
return elemFile.value = ''; return elemFile.value = '';
} }
//选择文件的回调 // 选择文件的回调
if(type === 'choose' || options.auto){ if(type === 'choose' || options.auto){
options.choose && options.choose(args); options.choose && options.choose(args);
if(type === 'choose'){ if(type === 'choose'){
@ -446,7 +454,7 @@ layui.define(['lay','layer'], function(exports){
} }
} }
//检验文件数量 // 检验文件数量
that.fileLength = function(){ that.fileLength = function(){
var length = 0; var length = 0;
var items = getFiles(); var items = getFiles();
@ -457,10 +465,12 @@ layui.define(['lay','layer'], function(exports){
}(); }();
if(options.number && that.fileLength > options.number){ if(options.number && that.fileLength > options.number){
return that.msg( return that.msg(typeof text['limit-number'] === 'function'
? text['limit-number'](options, that.fileLength)
: (
'同时最多只能上传: '+ options.number + ' 个文件' '同时最多只能上传: '+ options.number + ' 个文件'
+'<br>您当前已经选择了: '+ that.fileLength +' 个文件' +'<br>您当前已经选择了: '+ that.fileLength +' 个文件'
); ));
} }
// 检验文件大小 // 检验文件大小
@ -475,7 +485,9 @@ layui.define(['lay','layer'], function(exports){
limitSize = size; limitSize = size;
} }
}); });
if(limitSize) return that.msg('文件大小不能超过 '+ limitSize); if(limitSize) return that.msg(typeof text['limit-size'] === 'function'
? text['limit-size'](options, limitSize)
: '文件大小不能超过 '+ limitSize);
} }
send(); send();

View File

@ -131,48 +131,95 @@ layui.define('jquery', function(exports){
setTopBar(); setTopBar();
}, 100); }, 100);
}); });
} },
//倒计时 // 倒计时
,countdown: function(endTime, serverTime, callback){ countdown: function(options){
var that = this var that = this;
,type = typeof serverTime === 'function'
,end = new Date(endTime).getTime() // 默认可选项
,now = new Date((!serverTime || type) ? new Date().getTime() : serverTime).getTime() options = $.extend(true, {
,count = end - now date: new Date(),
,time = [ now: new Date()
Math.floor(count/(1000*60*60*24)) //天 }, options);
,Math.floor(count/(1000*60*60)) % 24 //时
,Math.floor(count/(1000*60)) % 60 //分 // 兼容旧版参数
,Math.floor(count/1000) % 60 //秒 var args = arguments;
]; if(args.length > 1){
options.date = new Date(args[0]);
options.now = new Date(args[1]);
options.clock = args[2];
}
// 实例对象
var inst = {
options: options,
clear: function(){ // 清除计时器
clearTimeout(inst.timer);
},
reload: function(opts){ // 重置倒计时
this.clear();
$.extend(true, this.options, {
now: new Date()
}, opts);
count();
}
};
typeof options.ready === 'function' && options.ready();
// 计算倒计时
var count = (function fn(){
var date = new Date(options.date);
var now = new Date(options.now);
var countTime = function(time){
return time > 0 ? time : 0;
}(date.getTime() - now.getTime());
var result = {
d: Math.floor(countTime/(1000*60*60*24)), // 天
h: Math.floor(countTime/(1000*60*60)) % 24, // 时
m: Math.floor(countTime/(1000*60)) % 60, // 分
s: Math.floor(countTime/1000) % 60 // 秒
};
var next = function(){
now.setTime(now.getTime() + 1000);
options.now = now;
count();
};
// 兼容旧版返回值
if(args.length > 1) result = [result.d,result.h,result.m,result.s]
// 计时 - 以秒间隔
inst.timer = setTimeout(next, 1000);
typeof options.clock === 'function' && options.clock(result, inst);
// 计时完成
if(countTime <= 0){
clearTimeout(inst.timer);
typeof options.done === 'function' && options.done(result, inst);
};
return fn;
})();
if(type) callback = serverTime; return inst;
},
var timer = setTimeout(function(){
that.countdown(endTime, now + 1000, callback);
}, 1000);
callback && callback(count > 0 ? time : [0,0,0,0], serverTime, timer);
if(count <= 0) clearTimeout(timer);
return timer;
}
//某个时间在当前时间的多久前 // 某个时间在当前时间的多久前
,timeAgo: function(time, onlyDate){ timeAgo: function(time, onlyDate){
var that = this var that = this;
,arr = [[], []] var arr = [[], []];
,stamp = new Date().getTime() - new Date(time).getTime(); var stamp = new Date().getTime() - new Date(time).getTime();
//返回具体日期 // 返回具体日期
if(stamp > 1000*60*60*24*31){ if(stamp > 1000*60*60*24*31){
stamp = new Date(time); stamp = new Date(time);
arr[0][0] = that.digit(stamp.getFullYear(), 4); arr[0][0] = that.digit(stamp.getFullYear(), 4);
arr[0][1] = that.digit(stamp.getMonth() + 1); arr[0][1] = that.digit(stamp.getMonth() + 1);
arr[0][2] = that.digit(stamp.getDate()); arr[0][2] = that.digit(stamp.getDate());
//是否输出时间 // 是否输出时间
if(!onlyDate){ if(!onlyDate){
arr[1][0] = that.digit(stamp.getHours()); arr[1][0] = that.digit(stamp.getHours());
arr[1][1] = that.digit(stamp.getMinutes()); arr[1][1] = that.digit(stamp.getMinutes());
@ -181,22 +228,22 @@ layui.define('jquery', function(exports){
return arr[0].join('-') + ' ' + arr[1].join(':'); return arr[0].join('-') + ' ' + arr[1].join(':');
} }
//30天以内返回“多久前” // 30 天以内,返回「多久前」
if(stamp >= 1000*60*60*24){ if(stamp >= 1000*60*60*24){
return ((stamp/1000/60/60/24)|0) + ' 天前'; return ((stamp/1000/60/60/24)|0) + ' 天前';
} else if(stamp >= 1000*60*60){ } else if(stamp >= 1000*60*60){
return ((stamp/1000/60/60)|0) + ' 小时前'; return ((stamp/1000/60/60)|0) + ' 小时前';
} else if(stamp >= 1000*60*3){ //3分钟以内为刚刚 } else if(stamp >= 1000*60*3){ // 3 分钟以内为:刚刚
return ((stamp/1000/60)|0) + ' 分钟前'; return ((stamp/1000/60)|0) + ' 分钟前';
} else if(stamp < 0){ } else if(stamp < 0){
return '未来'; return '未来';
} else { } else {
return '刚刚'; return '刚刚';
} }
} },
//数字前置补零 // 数字前置补零
,digit: function(num, length){ digit: function(num, length){
var str = ''; var str = '';
num = String(num); num = String(num);
length = length || 2; length = length || 2;
@ -204,10 +251,10 @@ layui.define('jquery', function(exports){
str += '0'; str += '0';
} }
return num < Math.pow(10, length) ? str + (num|0) : num; return num < Math.pow(10, length) ? str + (num|0) : num;
} },
//转化为日期格式字符 // 转化为日期格式字符
,toDateString: function(time, format){ toDateString: function(time, format){
//若 null 或空字符,则返回空字符 //若 null 或空字符,则返回空字符
if(time === null || time === '') return ''; if(time === null || time === '') return '';
@ -236,10 +283,10 @@ layui.define('jquery', function(exports){
.replace(/HH/g, hms[0]) .replace(/HH/g, hms[0])
.replace(/mm/g, hms[1]) .replace(/mm/g, hms[1])
.replace(/ss/g, hms[2]); .replace(/ss/g, hms[2]);
} },
//转义 html // 转义 html
,escape: function(html){ escape: function(html){
var exp = /[<"'>]|&(?=#[a-zA-Z0-9]+)/g; var exp = /[<"'>]|&(?=#[a-zA-Z0-9]+)/g;
if(html === undefined || html === null) return ''; if(html === undefined || html === null) return '';
@ -249,20 +296,20 @@ layui.define('jquery', function(exports){
return html.replace(/&(?!#?[a-zA-Z0-9]+;)/g, '&amp;') return html.replace(/&(?!#?[a-zA-Z0-9]+;)/g, '&amp;')
.replace(/</g, '&lt;').replace(/>/g, '&gt;') .replace(/</g, '&lt;').replace(/>/g, '&gt;')
.replace(/'/g, '&#39;').replace(/"/g, '&quot;'); .replace(/'/g, '&#39;').replace(/"/g, '&quot;');
} },
//还原转义的 html // 还原转义的 html
,unescape: function(html){ unescape: function(html){
if(html === undefined || html === null) html = ''; if(html === undefined || html === null) html = '';
html += ''; html += '';
return html.replace(/\&amp;/g, '&') return html.replace(/\&amp;/g, '&')
.replace(/\&lt;/g, '<').replace(/\&gt;/g, '>') .replace(/\&lt;/g, '<').replace(/\&gt;/g, '>')
.replace(/\&#39;/g, '\'').replace(/\&quot;/g, '"'); .replace(/\&#39;/g, '\'').replace(/\&quot;/g, '"');
} },
// 打开新窗口 // 打开新窗口
,openWin: function(options){ openWin: function(options){
var win; var win;
options = options || {}; options = options || {};
win = options.window || window.open((options.url || ''), options.target, options.specs); win = options.window || window.open((options.url || ''), options.target, options.specs);
@ -270,10 +317,10 @@ layui.define('jquery', function(exports){
win.document.open('text/html', 'replace'); win.document.open('text/html', 'replace');
win.document.write(options.content || ''); win.document.write(options.content || '');
win.document.close(); win.document.close();
} },
//让指定的元素保持在可视区域 // 让指定的元素保持在可视区域
,toVisibleArea: function(options){ toVisibleArea: function(options){
options = $.extend({ options = $.extend({
margin: 160 //触发动作的边界值 margin: 160 //触发动作的边界值
,duration: 200 //动画持续毫秒数 ,duration: 200 //动画持续毫秒数
@ -298,10 +345,10 @@ layui.define('jquery', function(exports){
obj[SCROLL_NAME] = thisOffset - size/2 + scrollValue obj[SCROLL_NAME] = thisOffset - size/2 + scrollValue
scrollElem.animate(obj, options.duration); scrollElem.animate(obj, options.duration);
} }
} },
//批量事件 //批量事件
,event: function(attr, obj, eventType){ event: function(attr, obj, eventType){
var _body = $('body'); var _body = $('body');
eventType = eventType || 'click'; eventType = eventType || 'click';