只针对若依框架的html部分代码:
想要的效果,选中多选项,实现指定元素节点的新增(各种方式实现都不理想,只能自己一点点拼了):
效果:
移除:
代码: 复制指定节点(页面初始化生成的被隐藏的节点,id为 div_replace_id);遍历验证新增节点各项元素数值;提交时获取新增节点下的所有数据,封装为json字符串 。复制的节点被bootstrap进行了二次编码,所以js里对被复制节点代码做了各种自定义删减
<!DOCTYPE HTML>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<meta charset="utf-8">
<head th:include="include :: header"></head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-boomWorkTask-add" th:object="${merchantOrder}">
<input id="merchantOrderId" name="merchantOrderId" class="form-control" type="hidden" th:value="*{merchantOrderId}">
<input id="merchantOrderTitle" name="merchantOrderTitle" class="form-control" type="hidden" th:value="*{merchantOrderTitle}">
<input id="channelsJson" name="channelsJson" class="form-control" type="hidden">
<div class="form-group">
<label class="col-sm-3 control-label">任务类型:</label>
<div class="col-sm-8">
<input id="taskType" name="taskType" type="hidden" value="1">
<span id="taskTypeSpan" name="taskTypeSpan" th:each="dict:${@dict.getType('boom_task_type')}" th:class="${dict.dictValue == '1' ? ' badge badge-success taskTypeSpan ' : 'badge badge-default taskTypeSpan '}" th:text="| ${dict.dictLabel} |" th:value ="${dict.dictValue}" th:onclick="selectTaskTypeSpan(this,[[${dict.dictValue}]])" style="margin: 0.5rem;padding: 0.8rem;font-size:12px;cursor:pointer;"/>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">类目:</label>
<div class="col-sm-4">
<select name="dictCategoryKV" id="dictCategoryKV" th:with="dictList=${@dict.getType('talent_category')}" class="selectpicker" title="请选择类目" data-live-search="true" >
<option th:each="dict : ${dictList}" th:text="${dict.dictLabel}"
th:value="|${dict.dictValue},${dict.dictLabel}|"></option>
</select>
</div>
<label class="dictCategoryKVTip" style="color:#ef392b;"></label>
</div>
<!--
下拉检索渠道
<div class="form-group">
<label class="col-sm-3 control-label">渠道:</label>
<div class="col-sm-8">
<select name="dictChannelKV" id="dictChannelKV" th:with="dictList=${@dict.getType('talent_channel')}" class="selectpicker" multiple title="请选择渠道" data-live-search="true" >
<option th:each="dict : ${dictList}" th:text="${dict.dictLabel}"
th:value="|${dict.dictValue},${dict.dictLabel}|"></option>
</select>
</div>
<label class="dictChannelKVTip" style="color:#ef392b;"></label>
</div>
-->
<div class="form-group">
<label class="col-sm-3 control-label">渠道:</label>
<div class="col-sm-8">
<span th:each="dict:${@dict.getType('talent_channel')}" th:id ="'channelsSpan_'+${dict.dictValue}" th:class="${dict.dictValue == '1' ? ' badge badge-success channelsSpan ' : 'badge badge-default channelsSpan '}" th:text="| ${dict.dictLabel} |" th:value ="${dict.dictValue}" th:onclick="selectChannelSpan(this,[[${dict.dictValue}]],[[${dict.dictLabel}]])" style="margin: 0.5rem;padding: 0.8rem;font-size:12px;cursor:pointer;"/>
</div>
</div>
<!--
原多选方式(弃用)
<div class="form-group">
<label class="col-sm-3 control-label">渠道:</label>
<div class="col-sm-9">
<label th:each="dict:${@dict.getType('talent_channel')}" class="check-box" onclick="addText(this)">
<input id="channelsKVArray" name="channelsKVArray" type="checkbox" th:value="|${dict.dictValue}@${dict.dictLabel}|" th:text="${dict.dictLabel}">
</label>
</div>
</div>
-->
<div class="form-group">
<label class="col-sm-3 control-label">各渠道内容:</label>
<div class="col-sm-8">
</div>
</div>
<hr width="70%"/>
<!-- 渠道池 -->
<div id="push_channels">
<!-- 隐藏节点(追加渠道时复制此节点) start -->
<div id="div_replace_id" class="div_replace_base" hidden>
<div class="form-group">
<label class="col-sm-3 control-label"></label>
<div class="col-sm-8">
<input id="channelName" class="" hidden th:value="渠道名">
<label style="margin-top: 9px;font-size: 16px;font-weight: bold;">渠道名:</label>
<label style="color: red;font-size: 16px;float: right;cursor:pointer;" title="删除" onclick="removeChannel('div_replace_id')"> x </label>
</input>
</div>
<div class="form-group">
<label class="col-sm-3 control-label"></label>
<div class="col-sm-4" >
<input id="articleType" type="hidden" value="0">
<span id="articleTypeSpan" th:each="dict:${@dict.getType('article_type')}" th:class="${dict.dictValue == '0' ? ' badge badge-success articleTypeSpanClass ' : 'badge badge-default articleTypeSpanClass '}" th:text="| ${dict.dictLabel} |" th:value ="${dict.dictValue}" th:onclick="selectArticleTypeSpan_rep,[[${dict.dictValue}]])" style="margin: 0.5rem;padding: 0.8rem;font-size:12px;cursor:pointer;"/>
</div>
<div class="col-sm-4">
<input id="workNum" class="form-control" type="number" placeholder="内容数量">
</div>
<label class="workNumTip" style="color:#ef392b;"></label>
</div>
<div class="form-group">
<label class="col-sm-3 control-label"></label>
<div class="col-sm-4">
<select id="staffKV" class="selectpicker" title="选择执行人" data-live-search="true" >
<option th:each="map : ${staffList}" th:text="${map.mapValue}"
th:value="|${map.mapKey},${map.mapValue}|" ></option>
</select>
</div>
<div class="col-sm-4" style="margin-left:3px;" >
<input type="text" placeholder="计划任务结束日期" class="layui-input form-control " id="planEndDate" th:value="*{#dates.format(planEndDate,'yyyy-MM-dd')}">
</div>
<label class="staffKVTip" style="color:#ef392b;"></label>
</div>
<div class="form-group">
<label class="col-sm-3 control-label"></label>
<div class="col-sm-8">
<textarea id="taskInfo" class="form-control" placeholder="任务描述" th:field="*{orderNote}"></textarea>
</div>
</div>
<hr width="70%"/>
</div>
</div>
<!-- 隐藏节点(追加渠道时复制此节点) end -->
</div>
</form>
</div>
<div th:include="include::footer"></div>
<script type="text/javascript">
var prefix = ctx + "system/boomWorkTask";
//注意:
layui.use(['laydate'], function(){
var laydate = layui.laydate;
//执行一个laydate实例
laydate.render({
elem: '#planEndDate', //指定元素
done:function(value,date){//value, date, endDate点击日期、清空、现在、确定均会触发。回调返回三个参数,分别代表:生成的值、日期时间对象、结束的日期时间对象
if(value.length == 10){
// reloadData(value);//默认加载当日数据
}
}
});
});
$("#form-boomWorkTask-add").validate({
rules:{
// workTaskTitle:{
// required:true,
// },
// workNum:{
// required:true,
// },
// taskInfo:{
// required:true,
// },
}
});
function submitHandler() {
cleanTips();
if ($.validate.form()) {
if(add_validate() == false){
return false;
}
$.operate.save(prefix + "/add", $('#form-boomWorkTask-add').serialize());
}
}
//验证并提示
function add_validate() {
if($("#dictCategoryKV").val() == ""){
$(".dictCategoryKVTip").html("*必选");
$.modal.msgError("未选择类目");
$("#dictCategoryKV").focus();
return false;
}
//下面是遍历带有名为div_replace的class节点下的各元素数值
var eachBoolean = true;
var jsonArr = [];
var i = 0;
$('div').filter('.div_replace').each(function() {
var eachJson = {};
var channelId = $(this).attr('id');
eachJson["channelId"] = channelId;
eachJson["channelName"] = $(this).find($("#channelName_"+channelId)).val();
eachJson["articleType"] = $(this).find($("#articleType_"+channelId)).val();
var workNum_Element = $(this).find($("#workNum_"+channelId));
var workNum = workNum_Element.val();
if(workNum == "" || parseInt(workNum) < 1){
$.modal.msgError("请录入正确数值");
workNum_Element.focus();
eachBoolean = false;
return false;
}else{
if(parseInt(workNum) > 1000){
$.modal.msgError("内容最大分配数为1000,请拆分任务");
workNum_Element.focus();
eachBoolean = false;
return false;
}
}
eachJson["workNum"] = workNum;
var staff_Element = $(this).find($("#staffKV_"+channelId));
var staffKV = staff_Element.val();
if(staffKV == ""){
$.modal.msgError("未选择执行人");
staff_Element.focus();
eachBoolean = false;
return false;
}
eachJson["staffKV"] = staffKV;
var planEndDate_Element = $(this).find($("#planEndDate_"+channelId));
var planEndDate = planEndDate_Element.val();
if(planEndDate == "" ){
$.modal.msgError("未选择日期");
planEndDate_Element.focus();
eachBoolean = false;
return false;
}
eachJson["planEndDate"] = planEndDate;
eachJson["taskInfo"] = $(this).find($("#taskInfo_"+channelId)).val();
jsonArr[i] = eachJson;
i = i+1;
});
if(eachBoolean === false){
return false;
}
var jsonStr = JSON.stringify(jsonArr);
if(jsonStr == "[]"){
$.modal.msgError("请选择渠道并录入数据");
return false;
}else{
$("#channelsJson").val(jsonStr);
}
}
//清空提示
function cleanTips() {
$(".dictCategoryKVTip").html("");
$(".dictChannelKVTip").html("");
// $(".talentKVTip").html("");
$(".staffKVTip").html("");
}
//
function selectTaskTypeSpan(taskTypeElement,taskTypeValue) {
$(".taskTypeSpan").removeClass("badge-default badge-success"); //移除样式
$(".taskTypeSpan").addClass("badge-default"); //初始化背景样式
var taskType = $("#taskType").val();
if(taskTypeValue == taskType){
//取消
$("#taskType").val(0);
}else{
//选中
$("#taskType").val(taskTypeValue);
$(taskTypeElement).addClass("badge-success");
}
}
function selectArticleTypeSpan(articleTypeElement,channelId,articleTypeValue) {
$(".articleTypeSpanClass_"+channelId).removeClass("badge-default badge-success"); //移除样式
$(".articleTypeSpanClass_"+channelId).addClass("badge-default"); //初始化背景样式
var articleType = $("#articleType_"+channelId).val();
if(articleTypeValue == articleType){
//取消
$("#articleType_"+channelId).val(0);
}else{
//选中
$("#articleType_"+channelId).val(articleTypeValue);
$(articleTypeElement).addClass("badge-success");
}
}
function selectChannelSpan(element,value,label){
if($(element).hasClass("badge-success")){
removeChannel(value);//移除渠道
}else{
//-------------拷贝渠道信息录入节点,并替换各种属性值-------------
var base_div_html = $("#div_replace_id").prop("outerHTML");//拷贝指定元素及其下属元素
// console.error(base_div_html); //打印追加的节点原始代码
base_div_html = base_div_html.replace('class="div_replace_base"','class="div_replace"' );//替换类名
base_div_html = base_div_html.replace('hidden=""',"" );//取消隐藏 替换第一次出现的某个字符串
base_div_html = base_div_html.replace('渠道名',label );//替换渠道名
base_div_html = base_div_html.replace('渠道名',label );//二次替换渠道名
base_div_html = base_div_html.replace('id="channelName"','id="channelName_'+ value+'"');//替换
base_div_html = base_div_html.replace('id="workNum"','id="workNum_'+ value+'"');//替换
base_div_html = base_div_html.replace('id="taskInfo"','id="taskInfo_'+ value+'"');//替换
base_div_html = base_div_html.replace('id="staffKV"','id="staffKV_'+value+'"');
base_div_html = base_div_html.replace('articleTypeSpanClass ',"articleTypeSpanClass_"+ value);//替换
base_div_html = base_div_html.replace('articleTypeSpanClass ',"articleTypeSpanClass_"+ value);//替换
base_div_html = base_div_html.replace('id="articleType"','id="articleType_'+value+'"');
var re = new RegExp("selectArticleTypeSpan_rep,","g"); //定义正则表达式 第一个参数是要替换掉的内容,第二个参数"g"表示替换全部(global)。
base_div_html = base_div_html.replace(re,'selectArticleTypeSpan(this,'+value+',');//第一个参数是正则表达式 全局替换所有指定字符串
base_div_html = base_div_html.replace('id="planEndDate"','id="planEndDate_'+value+'"');//日期id
base_div_html = base_div_html.replace('lay-key="1"','lay-key="'+value+'"');//日期id
var bs = '<div class="dropdown bootstrap-select bs3">';
base_div_html = base_div_html.replace(bs,"" );//去掉下拉框上级div 注意这里闭合的</div>需要在下面r字符串末尾一起去掉
var nul_option = '<option class="bs-title-option" value=""></option>';
base_div_html = base_div_html.replace(nul_option,"" );//去掉多余空选项
var r = '<button type="button" class="btn dropdown-toggle btn-default bs-placeholder" data-toggle="dropdown" role="combobox" aria-owns="bs-select-2" aria-haspopup="listbox" aria-expanded="false" data-id="staffKV" title="选择执行人"><div class="filter-option"><div class="filter-option-inner"><div class="filter-option-inner-inner">选择执行人</div></div> </div><span class="bs-caret"><span class="caret"></span></span></button><div class="dropdown-menu open"><div class="bs-searchbox"><input type="text" class="form-control" autocomplete="off" role="combobox" aria-label="Search" aria-controls="bs-select-2" aria-autocomplete="list"></div><div class="inner open" role="listbox" id="bs-select-2" tabindex="-1"><ul class="dropdown-menu inner " role="presentation"></ul></div></div></div>';
base_div_html = base_div_html.replace(r,"");//去掉多余下拉框(下面会重新渲染一个下拉框)
var re = new RegExp("div_replace_id","g"); //定义正则表达式 第一个参数是要替换掉的内容,第二个参数"g"表示替换全部(global)。
base_div_html = base_div_html.replace(re, value); //第一个参数是正则表达式 全局替换所有指定字符串
// console.error(base_div_html); //打印追加的节点
// 各控件新增class 用于获取控件内容值
//向渠道大节点push_channels 追加新的渠道录入节点
$("#push_channels").append(base_div_html);
//-------------重新渲染下拉框-------------
//使用refresh方法更新UI以匹配新状态。
$('#'+'staffKV_'+value).selectpicker('refresh');
//render方法强制重新渲染引导程序 - 选择ui。
$('#'+'staffKV_'+value).selectpicker('render');
//-------------重新渲染时间控件-------------
layui.use(['laydate'], function(){
var laydate = layui.laydate;
//执行一个laydate实例
laydate.render({
elem: '#planEndDate_'+value,
done:function(value,date){//value, date, endDate点击日期、清空、现在、确定均会触发。回调返回三个参数,分别代表:生成的值、日期时间对象、结束的日期时间对象
if(value.length == 10){
// reloadData(value);//默认加载当日数据
}
}
});
});
//选中渠道
$(element).addClass("badge-success");
}
}
//失去焦点监听事件
$("#workTaskTitle").on('blur', function(){
checkWorkTaskTitle();
});
//达人名存在提示
function showWorkTaskTip(){
$("#workTaskTitle-error").css("display","block");
$("#workTaskTitle-error").html("<i class=\"fa fa-times-circle\"></i> 标题重复");
}
function removeChannel(channel) {
$.modal.confirm("删除渠道内容?", function() {
//移除渠道内容元素
$("#"+channel).remove();
//移除选中样式
$("#channelsSpan_"+channel).removeClass("badge-success"); //移除样式
$("#channelsSpan_"+channel).addClass("badge-default"); //初始化背景样式
});
}
//检查达人名是否存在
function checkWorkTaskTitle() {
var url = prefix + "/checkWorkTaskTitle";
var workTaskTitle = $("#workTaskTitle").val();
if (workTaskTitle != '') {
$.ajax({
url: url,
data: {"workTaskTitle": workTaskTitle},
async: false,
type: "post",
success: function (result) {
if(result.code == 500){
showWorkTaskTip();
}
}
});
}
}
$(function() {
$.fn.extend({
onoffswitch: function() {
if (this.length > 0 && !this.is('div')) {
alert('请正确初始化onoffswitch控件');
return;
}
this.each(function(i, ele) {
var $ele = $(ele);
if ($ele.data('onoffswitch')) { // 已经初始化过了
return true;
}
$ele.find(':checkbox').click(function() {
setValue(this);
}).each(function() {
setValue(this);
});
setValue(this);
});
function setValue(input) {
var $input = $(input),
ry_value = $input.attr('ry-alue'); // value 为1,0 第一个为不选中,第二个为选中
if (!ry_value) {
return;
}
if ($input.is(':checked')) {
$input.val(ry_value.split(',')[1]);
} else {
$input.val(ry_value.split(',')[0]);
}
}
}
});
$('div.onoffswitch').onoffswitch();
});
</script>
</body>
</html>