JS UI组件
0.综述
0.1.原则
懒惰是改变世界的动力
分享是提升自己的动力
有现成的就用现成的, 不用重复的制造轮子
0.2.基本套路
1) 预定功能
2) 网络 查询备选
3) 引入控件包 , 测试 例子
4) 问题 解决
0.3.常见 控件库
界面UI框架 Bootstrap https://www.bootcss.com/, layUI (已下线)https://www.layui.site/index.htm
基于 vue.js 的 ElementUI https://element.eleme.cn/#/zh-CN
小控件库 JQueryUI https://jqueryui.com/ , JQueryEasyUI http://www.jeasyui.com/等
0.4.常见 案例库
除对应官网,
菜鸟教程 https://www.runoob.com/
w3school 在线教程 https://www.w3school.com.cn/
1.时间控件
1.1. bootstrap-datetimepicker
基于 bootstrap 是的 时间控件
1.1.1.先导入控件包
<link rel="stylesheet" th:href="@{/static/bower_components/bootstrap/dist/css/bootstrap.css}">
<link rel="stylesheet" th:href="@{/static/bower_components/bootstrap/dist/css/bootstrap-datetimepicker.min.css}">
<script th:src="@{/static/bower_components/jquery/dist/jquery.min.js}"></script>
<script th:src="@{/static/bower_components/bootstrap/dist/js/bootstrap.js}"></script>
<script th:src="@{/static/bower_components/bootstrap/dist/js/bootstrap-datetimepicker.min.js}"></script>
<script th:src="@{/static/bower_components/bootstrap/dist/locales/bootstrap-datetimepicker.zh-CN.js}"></script>
1.1.2.添加测试元素
<input type="text" id="testTime" name="testTime" class="form-control" placeholder="请输入时间">
1.1.3.再导入脚本
$("#testTime").datetimepicker({
language: 'zh-CN', //用自己设置的时间文字
weekStart: 1, //一周从那天开始,默认为0,从周日开始,可以设为1从周一开始
// startDate:"2018-5-20", //开始时间,可以写字符串,也可以直接写日期格式new Date(),在这之前的日期不能选择
//endDate:"2018-6-20",
//daysOfWeekDisabled: [0,4,6], //一周的周几不能选
todayBtn: 1, //是否显示今天按钮,0为不显示
autoclose: 1, //选完时间后是否自动关闭
todayHighlight: 1, //高亮显示当天日期
startView: 2, //0从小时视图开始,选分;1 从天视图开始,选小时;2从月视图开始,选天;3从年视图开始,选月;4从十年视图开始,选年
minView: 0,//最精确时间,默认0;0从小时视图开始,选分;1从天视图开始,选小时;2从月视图开始,选天;3从年视图开始,选月;4从十年视图开始,选年
//maxView:4, //默认值:4, ‘decade’
//keyboardNavigation:true, //是否可以用键盘方向键选日期,默认true
forceParse: 0, //强制解析,你输入的可能不正规,但是它胡强制尽量解析成你规定的格式(format)
format: 'yyyy-mm-dd hh:ii:ss',// 格式,注意ii才是分,mm或MM都是月
minuteStep:5, //选择分钟时的跨度,默认为5分钟
//pickerPosition:"top-right", // ‘bottom-left’,’top-right’,’top-left’’bottom-right’
showMeridian:0, //在日期和小时选择界面,出现上下午的选项,默认false
// showSecond: false,
// showMillisec: true,
//timeFormat: 'hh:mm:ss:l',
//bootcssVer: 3,
});
1.2.layDate
https://www.layui.site/doc/modules/laydate.html
1.2.1. 导入 layui 包
<link rel="stylesheet" type="text/css" th:href="@{/static/layui/css/layui.css}" >
<script type="text/javascript" th:src="@{/static/layui/layui.all.js}" ></script>
1.2.2. 添加测试元素
<div class="layui-inline">
<label class="layui-form-label">日期时间选择器</label>
<div class="layui-input-inline">
<input type="text" class="layui-input" id="test5" placeholder="yyyy-MM-dd HH:mm:ss">
</div>
</div>
1.2.3. 脚本
layui.use('laydate', function() {
var laydate = layui.laydate;
//日期时间选择器
laydate.render({
elem: '#test5'
, type: 'datetime'
});
})
format属性控制 显示的格式 yyyy-MM-dd HH:mm:ss
type 属性控制 显示的 内容 year, month , date , time , datetime
1.2.4.设置可选时间范围
页面元素
<div class="layui-form-item">
<label class="layui-form-label">开始时间</label>
<div class="layui-input-inline">
<input type="date" id="beginTime" name="ctBeginDate" lay-verify="title"
placeholder="请输入开始时间" class="layui-input" onblur="closeStartDate(this)" >
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">时间范围</label>
<div class="layui-input-inline">
<input type="text" class="layui-input" id="test6" placeholder="yyyy-MM-dd HH:mm:ss" style="width: 600px;">
</div>
</div>
JS 脚本
layui.use('laydate', function() {
var laydate = layui.laydate;
//日期时间选择器
startDate = laydate.render({
elem: '#test6'
,type: 'datetime'
,min: $("#beginTime").val()
});
})
function closeStartDate(dateInput) {
console.log(dateInput.value);
var date = dateInput.value.toString().split("-")
startDate.config.min = {
year: date[0],
month: parseInt(date[1]) -1, //关键 月份+1
date: date[2]
};
}
2.提交校验
2.1.html5自带校验
2.2.jquery-validate
基于 JQuery及BootStrap或者layUI的校验框架
2.2.1.先导入控件包
<script th:src="@{/static/bower_components/jquery/dist/jquery.min.js}"></script>
<script th:src="@{/static/plugins/jquery-validation-1.19.1/dist/jquery.validate.js}"></script>
2.2.2.添加测试元素
表单加Id, 元素 name,
<form id="infoForm" class="form form-horizontal" method="post" th:action="@{/test/addSave}" >
<div class="col-md-8 col-md-offset-2">
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">基本信息</h3>
<div class="box-search">
<button type="button" class="btn btn-default pull-right" onclick="history.back()">返回</button>
</div>
</div>
<div class="box-body">
<div class="form-group">
<label class="col-sm-2 control-label">员工姓名</label>
<div class="col-sm-6">
<input type="text" class="form-control" name="empName" placeholder="请输入员工姓名" required="required">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">员工性别</label>
<div class="col-sm-6 radio text-left">
<label>
<input type="radio" th:value="1" name="empSex" >男
</label>
<label>
<input type="radio" th:value="0" name="empSex" >女
</label>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">入职时间</label>
<div class="col-sm-6 ">
<input type="date" class="form-control" name="empBeginDate" placeholder="请输入入职时间" >
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">工龄</label>
<div class="col-sm-6 ">
<input type="number" class="form-control" min="0" step="1" name="empLen" placeholder="请输入工龄" >
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">薪水</label>
<div class="col-sm-6 ">
<input type="number" min="0.01" step="0.01" class="form-control" name="empSalary" placeholder="请输入预招生人数" >
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">所属部门</label>
<div class="col-sm-6 ">
<select class="form-control" name="deptId" >
<option value="" >请选择</option>
<option value="1" >部门一</option>
<option value="2" >部门二</option>
</select>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">地址</label>
<div class="col-sm-8 ">
<textarea class="form-control" name="empAddr" placeholder="请输入地址" ></textarea>
</div>
</div>
<div class="box-footer">
<button type="button" class="btn btn-danger" onclick="cleanUp(this)">清空</button>
<button type="submit" class="btn btn-info pull-right">提交</button>
</div>
</div>
</div>
</div>
</form>
2.2.3.再导入脚本
页面加载后对表单进行验证 $(“#表单id名”).validate({})
在validate中的rules中编写验证规则
字段的name属性: “校验器” (tisps:一个输入框只有一个校验器的时候使用)
字段的name属性:{ 校验器:值, 校验器:值 } (tips:输入框需要有多个校验器的时候使用)
在validate中的messages中编写提示信息 (tips格式与rules相对应)
在validate中的 errorClass, errorElement, errorPlacement, highlight, highlight 来提示用户
在validate中的submitHandler中编写验证通过执行的内容
1 ) 脚本结构
$("#表单id名").validate({});
2 ) 规则与提示
rules: {
empName: "required",
empSex: "required",
empBeginDate: "required",
empLen: {
required: true,
min: 0,
number:true
},
empSalary: {
required: true,
range:[1000.0, 15000.0]
},
deptId: "required",
empAddr: {
required: true,
maxlength: 450
}
},
messages: {
empName: "请输入员工姓名",
empSex: "请选择员工性别",
empBeginDate: "请输入入职时间",
empLen: {
required: "请输入员工工龄",
min: "工龄要大于等于0年",
number: "工龄为整数数值"
},
empSalary: {
required: "请输入薪水",
range:"薪水要在1000.00元到15000.00元之间"
},
deptId: "请选择所属部门",
empAddr: {
required: "请输入员工说明",
maxlength: "员工说明最多450个字符"
}
},
常用的默认的规则
序号 | 校验类型 | 取值 | 描述 |
---|---|---|---|
1 | required | true&false | 必须填写的字段 |
2 | “@”&“email” | 必须输入正确格式的电子邮件 | |
3 | remote | url路径 | 使用ajax进行验证 |
4 | date | 数字 | 正确格式日期 tips:ie6有bug |
5 | dateISO | 字符串 | 正确格式的日期 例如:2018-11-28,2018/11/28 tips:只验证格式,不验证有效性 |
6 | number | true&false | 合法的数字 |
7 | digits | true&false | 整数 |
8 | creditcard | true&false | 合法的信用卡号 |
9 | equalTo | JQuery表达式(eg:“#regist_password”) | 输入值必须和 #regist_password相同。 |
11 | maxlength | 数字 | 最大长度 |
12 | minlength | 数字 | 最小长度 |
13 | rangelength | [min,max] | 输入长度必须在 min和 max之间的字符串(tips:汉字算一个字符) |
14 | range | [min,max] | 输入值必须在 min和 max之间的数字 |
15 | max | :n | 最大值不能大于n |
16 | min | :n | 最小值不能小于n |
3 ) 设置提示的形式
errorClass | String | 指定错误提示的 css 类名,可以自定义错误提示的样式。 | “error” |
---|---|---|---|
errorElement | String | 用什么标签标记错误,默认是 label,可以改成 em。 | “label” |
errorPlacement | function | 跟一个函数,可以自定义错误放到哪里。 | input元素之后 |
success | 要验证的元素通过验证后的动作, 如果跟一个字符串,会当作一个 css 类,也可跟一个函数。 | 无 | |
highlight | function | 可以给未通过验证的元素加效果、闪烁等。 | 无 |
***因为要用到 BootStrap的元素 所以也要 导入 bootstrap 相关库
errorElement : 'span',
errorClass : 'help-block',
//自定义错误消息放到哪里
errorPlacement : function(error, element) {
element.next().remove();//删除显示图标
element.after('<span class="glyphicon glyphicon-remove form-control-feedback" aria-hidden="true"></span>');
element.closest('div').append(error);//显示错误消息提示
},
//给未通过验证的元素进行处理
highlight : function(element) {
$(element).closest('div').addClass('has-error has-feedback');
},
//验证通过的处理
success : function(label) {
var el=label.closest('div').find("input,select,textarea");
el.next().remove();//与errorPlacement相似
el.after('<span class="glyphicon glyphicon-ok form-control-feedback" aria-hidden="true"></span>');
label.closest('div').removeClass('has-error').addClass("has-feedback has-success");
label.remove();
},
***因为要用到 layui 的元素 所以也要 导入 layui 相关库
//重写showErrors
showErrors: function (errorMap, errorList) {
var msg = "";
$.each(errorList, function (i, v) {
//msg += (v.message + "\r\n");
//在此处用了layer的方法,显示效果更美观
//在此处用了layer的方法,显示效果更美观
if($(v.element)[0].tagName.indexOf("SELECT")>-1){ // 针对于select2 控件做了调整
layer.tips(v.message, $(v.element).next(), {icon: 2 , time: 2000 });
}else{
layer.tips(v.message, v.element, {icon: 2 , time: 2000 });
}
return false;
});
},
4 ) 成功处理
submitHandler: function () {
console.log("ok")
// ... 提交表单
}
5 ) 自定义规则
验证 员工姓名必须是中文 , 要使用 正则表达式
// 验证 中文
jQuery.validator.addMethod("isCn", function(value, element) {
return this.optional(element) || (/^[\u4e00-\u9fa5]{1,}$/.test(value));
}, "请填写中文。");
规则与提示也变化
rules: {
empName: {
required:true,
isCn:true
},
},
messages: {
empName: {
required:"请输入员工姓名",
isCn:"员工姓名应该使用中文"
},
}
又如 电话号码
// 手机号码验证
jQuery.validator.addMethod("isPhone", function(value, element) {
var length = value.length;
return this.optional(element) || (length == 11 && /^1[3-9]\d{9}$/.test(value));
}, "请正确填写您的手机号码。");
6 ) ***远程判断
rules: {
empName: {
required:true,
isCn:true,
/* 用ajax判断数据库中用户名是否存在 */
remote:{
type: "post",
url: "/ycTest/ajaxCheckEmpName", // 返回 boolean 结果 true 验证通过, false 验证不通过
async:false, // 要使用 同步 通信
cache:false,
data:{
empName:function () {
return $("#empName").val();
}
},
// 当 controller 返回的内容不是 boolean 时 可以通过这个方式 进行处理
dataFilter:function (resp) {
if("no"==resp){
return false;
}else{
return true;
}
}
}
},
},
messages: {
empName: {
required:"请输入员工姓名",
isCn:"员工姓名应该使用中文",
remote:"通过远程判断输入信息有误"
},
}
3.图表
将数据图形化展示
3.1.baidu-echarts
官网: https://echarts.apache.org/zh/index.html
3.1.1.先导入控件包
<script th:src="@{/static/plugins/echarts/4.2.1/echarts.min.js}"></script>
<script th:src="@{/static/plugins/echarts/theme/主题.js}"></script>
3.1.2.添加测试元素
<div id="main" style="width: 1200px;height:400px;"></div>
3.1.3.再导入脚本
// 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('main'),'主题');
// 指定图表的配置项和数据
var option = {
title: {
text: 'ECharts 入门示例'
},
tooltip: {},
legend: {
data:['销量']
},
xAxis: {
data: ["衬衫","羊毛衫","雪纺衫","裤子","高跟鞋","袜子"]
},
yAxis: {},
series: [{
name: '销量',
type: 'bar',
data: [5, 20, 36, 10, 10, 20]
}]
};
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);
3.1.4. option 说明
title : 标题
tooltip : 提示
legend : 图例
toolbox : 工具箱
xAxis : x 坐标轴
yAxis : y 坐标轴
series : 数据
3.1.5. 工具箱代码
toolbox: {
show : true,
orient: 'horizontal', // 布局方式,默认为水平布局,可选为:
// 'horizontal' ¦ 'vertical'
x: 'right', // 水平安放位置,默认为全图右对齐,可选为:
// 'center' ¦ 'left' ¦ 'right'
// ¦ {number}(x坐标,单位px)
y: 'top', // 垂直安放位置,默认为全图顶端,可选为:
// 'top' ¦ 'bottom' ¦ 'center'
// ¦ {number}(y坐标,单位px)
color : ['#1e90ff','#22bb22','#4b0082','#d2691e'],
backgroundColor: 'rgba(0,0,0,0)', // 工具箱背景颜色
borderColor: '#ccc', // 工具箱边框颜色
borderWidth: 0, // 工具箱边框线宽,单位px,默认为0(无边框)
padding: 5, // 工具箱内边距,单位px,默认各方向内边距为5,
showTitle: true,
feature : {
dataZoom : {
show : true,
title : {
dataZoom : '区域缩放',
dataZoomReset : '区域缩放-后退'
}
},
dataView : {
show : true,
title : '数据视图',
readOnly: true,
lang : ['数据视图', '关闭', '刷新']
},
magicType: {
show : true,
title : {
line : '动态类型切换-折线图',
bar : '动态类型切换-柱形图',
},
type : ['line', 'bar']
},
restore : {
show : true,
title : '还原',
color : 'black'
},
saveAsImage : {
show : true,
title : '保存为图片',
type : 'jpeg',
lang : ['点击本地保存']
}
}
},
3.1.6. 图表对应数据
line , bar 拆线图 , 柱状图 : 对应一组数字 List
pie 饼图 : List<Map<String, Object>> name 对应 分类 value 对应 值
radar 雷达图 : List<Map<String, Object>> name 对应 分类 max 对应 最大值
List 对应 每一个分类的 值
3.1.7.取动态数据
$.ajax({
type:"post",
url:"/subject/queryStu",
success:function(resp){
subjNames = resp.subjNames;
stuCounts = resp.stuCounts;
myChart.setOption({
xAxis:{
data: subjNames
},
series: [{
data: stuCounts
}]
});
},
dataType:"json"
});
饼图
option = {
title: {
text: 'Referer of a Website',
subtext: 'Fake Data',
left: 'center'
},
tooltip: {
trigger: 'item'
},
legend: {
orient: 'vertical',
left: 'left'
},
series: [
{
name: 'Access From',
type: 'pie',
radius: '50%',
data: [
{ value: 1048, name: 'Search Engine' },
{ value: 735, name: 'Direct' },
{ value: 580, name: 'Email' },
{ value: 484, name: 'Union Ads' },
{ value: 300, name: 'Video Ads' }
],
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}
]
};
雷达图
option = {
title: {
text: 'Basic Radar Chart'
},
legend: {
data: ['Allocated Budget', 'Actual Spending']
},
radar: {
// shape: 'circle',
indicator: [
{ name: 'Sales', max: 6500 },
{ name: 'Administration', max: 16000 },
{ name: 'Information Technology', max: 30000 },
{ name: 'Customer Support', max: 38000 },
{ name: 'Development', max: 52000 },
{ name: 'Marketing', max: 25000 }
]
},
series: [
{
name: 'Budget vs spending',
type: 'radar',
data: [
{
value: [4200, 3000, 20000, 35000, 50000, 18000],
name: 'Allocated Budget'
},
{
value: [5000, 14000, 28000, 26000, 42000, 21000],
name: 'Actual Spending'
}
]
}
]
};
4.树 tree
4.1.JQuery EasyUI Tree
官网: https://www.jeasyui.net/plugins/185.html
4.1.1.先导入控件包
<link rel="stylesheet" type="text/css" th:href="@{/static/js/jquery-easyui-1.3.6/themes/default/easyui.css}">
<link rel="stylesheet" type="text/css" th:href="@{/static/js/jquery-easyui-1.3.6/themes/icon.css}">
<script th:src="@{static/bower_components/jquery/dist/jquery.min.js}"></script>
<script th:src="@{/static/js/jquery-easyui-1.3.6/jquery.easyui.min.js}"></script>
4.1.2.添加测试元素
<ul id="tt" class="easyui-tree" ></ul>
4.1.3.再导入脚本
$('#tt').tree({
url:'/sysMenu/roleMenuData?roleId=[[${sysRole.roleId}]]'
,checkbox:true
,onLoadSuccess:function(){
// 返回结点对象 返回根结点
var rootNode = $('#tt').tree('getRoot');
// 选中 返回结点
$('#tt').tree('select', rootNode.target);
}
,onClick:function (node) {
}
})
4.1.4.属性
id:节点的 id,它对于加载远程数据很重要。
text:要显示的节点文本。
state:节点状态,‘open’ 或 ‘closed’,默认是 ‘open’。当设置为 ‘closed’ 时,该节点有子节点,并且将从远程站点加载它们。
children:定义了一些子节点的节点数组。
checked:指示节点是否被选中。 true 结点被 选中 false 不会被选中
attributes:给一个节点添加的自定义属性集合。
target 属性 指目标 就是指向某个结点
var mm = [{
"id":0,
"text":"系统菜单",
"state":"open",
"attributes":{
"ntype":"root"
},
"children":[{
"id":4,
"text":"基本代码",
"state":"open",
"attributes":{
"ntype":"0"
},
"children":[{
"id":6,
"text":"友情连接",
"state":"open",
"attributes":{
"ntype":"1"
}
},{
"id":22,
"text":"物流信息",
"state":"open",
"attributes":{
"ntype":"1"
}
}]
},{
"id": 5,
"text": "商品信息",
"state": "open",
"attributes": {
"ntype": "0"
},
"children": [{
"id": 13,
"text": "商品维护",
"state": "open",
"attributes": {
"ntype": "1"
}
},{
"id": 14,
"text": "商品细分",
"state": "open",
"attributes": {
"ntype": "1"
}
}]
}
]}]
4.1.4.事件
onLoadSuccess 加载成功事件
onClick 点击
4.1.5.方法
getChecked 方法 返回 被 复选框 被 选中的结点
getRoot 方法 得到 根结点
select 选中方法
getChildren 得到子结点
getSelected 得到当前被 选中的那个结点
4.2.ztree
官网: http://www.treejs.cn/v3/main.php#_zTreeInfo
4.2.1.先导入控件包
<link rel="stylesheet" th:href="@{/static/ztree/css/zTreeStyle/zTreeStyle.css}">
<script th:src="@{/static/ztree/js/jquery.ztree.all.js}"></script>
4.2.2.添加测试元素
<ul id="treeDemo" class="ztree"></ul>
4.2.3.再导入脚本
var zTreeObj;
// zTree 的参数配置,深入使用请参考 API 文档(setting 配置详解)
var setting = {};
// zTree 的数据属性,深入使用请参考 API 文档(zTreeNode 节点数据详解)
var zNodes = [
{name:"test1", open:true, children:[
{name:"test1_1"}, {name:"test1_2"}]},
{name:"test2", open:true, children:[
{name:"test2_1"}, {name:"test2_2"}]}
];
$(document).ready(function(){
zTreeObj = $.fn.zTree.init($("#treeDemo"), setting, zNodes);
});
4.2.4.节点属性
id:节点的 id,它对于加载远程数据很重要。
name:要显示的节点文本。
open:节点状态,‘true’(打开) 或 ‘false’(关闭),默认是 ‘true’。
children:定义了一些子节点的节点数组。
checked:指示节点是否被选中。 true 结点被 选中 false 不会被选中
DIY:给一个节点添加的自定义属性集合。
4.2.5.setting设置
var setting = {
view: {
fontCss:{'color':'black','font-weight':'bold'},//字体样式函数
selectedMulti: true //设置是否允许同时选中多个节点
},
// 作用复选框 时使用
check: {
enable: true,
chkStyle: "checkbox",
chkboxType: { "Y": "ps", "N": "ps" } // p 代表 父级 s 代表 子级
}
};
4.2.6.异步加载数据
var zTreeObj;
// zTree 的参数配置,深入使用请参考 API 文档(setting 配置详解)
var setting = {
view: {
fontCss:{'color':'black','font-weight':'bold'},//字体样式函数
selectedMulti: true //设置是否允许同时选中多个节点
},
async: {
enable: true,
url: "/sysMenu/menuTreeData",
otherParam: { "id":"1", "name":"test"}, //向服务器传递的参数
dataFilter: ajaxDataFilter
}
};
zTreeObj = $.fn.zTree.init($("#treeDemo"), setting);
// 用于对 Ajax 返回数据进行预处理的函数
function ajaxDataFilter(treeId, parentNode, responseData) {
if (responseData) {
for(var i =0; i < responseData.length; i++) {
responseData[i].name += "_filter";
}
}
return responseData;
};
4.2.7.结点点击事件
设置属性
var setting = {
view: {
selectedMulti: false
},
callback: {
onClick: clickMe , // 设置点击事件对应的函数
onAsyncSuccess: zTreeOnAsyncSuccess // 异步加载成功后执行
}
};
// 处理 函数
// 参数 对应( js的事件对象, 树的id , 被点击的结点 )
function clickMe(event, treeId, treeNode) {
$("#addBtn").removeClass("layui-btn-disabled").prop("disabled", false);
$("#editBtn").removeClass("layui-btn-disabled").prop("disabled", false);
$("#delBtn").removeClass("layui-btn-disabled").prop("disabled", false);
console.log(treeNode.islink)
// 可以根据 结点属性进行操作
}
function zTreeOnAsyncSuccess(event, treeId, treeNode, msg) {
alert(msg);
var nodes = zTreeObj.getNodes();
console.log(nodes)
var node = zTreeObj.getNodeByParam("id", 0, null);
console.log(node)
zTreeObj.selectNode(node) // 让 指定 结点 被选中
};
4.2.8.方法
var rootNode = zTreeObj.getNodeByParam("id", 0, null); // 根据属性得到 指定结点
zTreeObj.selectNode(rootNode) // 让 指定 结点 被选中
var nodes = treeObj.getSelectedNodes(); // 得到 被选中的结点
var nodes = zTreeObj.getCheckedNodes(true); // 得到 被复选中的结点集合
5.模态窗
jscript->showModalDialog()
5.1.layer
基于 layui 的对话窗
5.1.1.先导入控件包
<link rel="stylesheet" th:href="@{/static/layui/css/layui.css}">
<script th:src="@{/static/js/jquery-3.2.1.min.js}"></script>
<!-- 导入 layui 的全部功能 -->
<script th:src="@{/static/layui/layui.all.js}"></script>
<!-- 也可以 只导入 layer 功能对应的 js 包 -->
<script th:src="@{/static/layui/layer.js}"></script>
5.1.2.添加测试元素
<button onclick="fn()">open</button>
5.1.3.再导入脚本
function fn(){
layer.open({
type: 2, // 可传入的值有:0(信息框,默认)** 1(页面层) ** 2(iframe层)3(加载层)4(tips层)
title:"标题",
skin: 'layui-layer-rim', //样式类名 蓝: layui-layer-lan 绿: layui-layer-molv
closeBtn: 1, // 0 不显示关闭按钮
anim: 2, // 进入的样式
shadeClose: true, //开启遮罩关闭
shade: 0.5,
area: ['420px', '240px'], //宽高
content: ['/ifr_child', 'no'],
maxmin: true,
fixed: false,//
btn: ['按钮一', '按钮二', '按钮三'],
btn3:function(index, layro){
alert(index)
console.log(layro)
},
btn2:function(index, layro){
// 得到 子窗口
// var iframeWin = window[layro.find('iframe')[0]['name']]
var iframeWin = window["layui-layer-iframe" + index];
var xx = iframeWin.cfn("parent");
console.log(xx)
},
yes: function (index, layro) {
alert("第一个按钮")
layer.closeAll(); //疯狂模式,关闭所有层
},
cancel:function () {
alert("close按钮")
}
})
}
*** 在子窗口中 使用parent 代表 父窗口
5.2.bootbox
基于 bootstrap 的模态窗
5.2.1.先导入控件包
要先导入 bootstrap 的包, 再导入 bootbox的包
<script th:src="@{/static/bower_components/bootbox/js/bootbox.js}"></script>
5.2.2.再导入脚本
bootbox.dialog({
// dialog的内容
message: "<iframe src='/index' name='ifr' style='width: 860px;height: 350px; border:0px solid;' ></iframe>",
// dialog的标题
title: "提示",
// 退出dialog时的回调函数,包括用户使用ESC键及点击关闭
onEscape: function() {},
// 是否显示此dialog,默认true
show: true,
// 是否显示body的遮罩,默认true
backdrop: true,
// 是否显示关闭按钮,默认true
closeButton: true,
// 是否动画弹出dialog,IE10以下版本不支持
animate: true,
// dialog的类名
className: "my_modal_position",
// 大 large , 小 small
size: "large",
// dialog底端按钮配置
buttons: {
// 其中一个按钮配置
success: {
label: "确定",
className: "btn-success",
// 点击按钮时的回调函数
callback: function() {
// ifr 代表子窗口 与 iframe 的 name 对应
}
},
// 另一个按钮配置
Danger: {
label: "取消",
className: "btn-danger",
callback: function() {}
}
}
})
6.富文本
6.1.simditor
官网: https://simditor.tower.im/
6.1.1.先导入控件包
<link rel="stylesheet" th:href="@{/static/simditor/css/simditor.css}">
<script th:src="@{/static/simditor/module.js}"></script>
<script th:src="@{/static/simditor/hotkeys.js}"></script>
<script th:src="@{/static/simditor/uploader.js}"></script>
<script th:src="@{/static/simditor/simditor.js}"></script>
6.1.2.添加测试元素
<textarea id="editor" placeholder="请输入内容" autofocus></textarea>
6.1.3.再导入脚本
var toolbar = ['title','bold','italic','underline','strikethrough','fontScale','color' ,'ol','ul','blockquote','code', 'table', 'link', 'image', 'hr', 'indent', 'outdent', 'alignment'];
var editor = new Simditor({
textarea: $('#editor'),
//optional options
toolbar:toolbar,
upload: {
url: '/example/fileUpload',
params: null,
fileKey: 'file',
connectionCount: 1,
leaveConfirm: '文件正在上传中,你确定要离开本页面吗?'
}
});
6.1.4.上传图片回传
要以 file_path 参数 回传图片存储路径
{
"success": true/false,
"msg": "error message", # optional
"file_path": "[real file path]"
}
6.2.TinyMCE
中文手册 : http://tinymce.ax-z.cn/
6.2.1.先导入控件包
<script th:src="@{/static/tinymce/tinymce.min.js}"></script>
6.2.2.添加测试元素
<textarea id="mytextarea" name="stuInfo" placeholder="请输入内容" autofocus></textarea>
6.2.3.再导入脚本
var plugins2 = 'link lists image code table colorpicker textcolor wordcount contextmenu'
var toolbar2 = 'bold italic underline strikethrough | fontsizeselect | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist | outdent indent blockquote | undo redo | link unlink image code | removeformat'
tinymce.init({
selector: '#mytextarea',
language: 'zh_CN',
content_style: "img {max-width:100%;}",
plugins: plugins2,
toolbar: toolbar2,
menubar: false,
autosave_ask_before_unload: false,
toolbar_drawer : false,
setup: function(stuInfo){
stuInfo.on('change',function(){ stuInfo.save(); });
},
//文件异步上传请求路径, 返回格式为{ location : "/demo/image/1.jpg" }
images_upload_url: '/tabStudent/fileUpload'
});
6.2.4.controller后台处理
@RequestMapping(value = "/tabStudent/fileUpload", method = {RequestMethod.GET,RequestMethod.POST})
@ResponseBody
public Map<String, Object> tinyFileUpload(MultipartFile file){
System.out.println("file.getOriginalFilename() = " + file.getOriginalFilename());
Map<String, Object> map = new HashMap<>();
if (!file.isEmpty()) {
String fileName = fileUtils.uploadToDisk(file,fileUtils.getTempFilePath());
map.put("msg", "成功");
map.put("location", "/temp/" + fileName);
} else {
map.put("msg", "失败");
}
return map;
}
6.2.5.上传图片回传
要以 location 参数 回传图片存储路径
{
location: "/temp/4e2c24b4-0475-4c8d-b149-ff1e4dbb02aa.png"
msg: "成功"
}
6.2.6.layui 不保存信息
在 init 函数里 增加 stuInfo 与 name属性值对应
setup: function(stuInfo){
stuInfo.on('change',function(){ stuInfo.save(); });
},
7.图片预览
7.1.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<img src="" alt="" id="mm" >
<input type="file" accept="image/*" id="ff" />
</body>
<script>
var ff = document.getElementById("ff")
ff.onchange= function(){
// 文件读取器
var r = new FileReader();
// 读取文件
r.readAsDataURL( ff.files[0] )
// 加载文件
r.onload = function(){
var mm = document.getElementById("mm")
// result 加载结果
mm.src = r.result
}
}
</script>
</html>
7.2.
<div style="width: 87px;height: 102px;border:1px solid gray;">
<img id="cover" th:src="@{/static/images/head.jpg}" alt=""
style="width: 85px;height: 100px;">
</div>
<input type="file" name="pic" placeholder="图片" onchange="yulan(this)"
class="layui-upload-button">
function yulan(input) {
var src = window.URL.createObjectURL(input.files[0]);
$("#cover").prop("src", src);
}