只是实现了前台页面的动态表单的设计,并未实现后台绑定数据到数据库等功能。技术使用到的为jquery和bootstrap。俗话说有图有真相,先说下具体效果如下:
点击添加一个面板容器:
容器添加成功:
实现的代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="../css/bootstrap.min.css">
<script src="../js/jquery-1.8.3.min.js"></script>
<script src="../js/bootstrap.min.js"></script>
</head>
<style type="text/css">
body{
background-color: rgba(0, 231, 68, 0.06);
}
/*隐藏的编辑面板属性的样式*/
.setPanel{
top:10%;
margin-left: 20%;
margin-right: 20%;
position: absolute;
border: solid 1px #000000;
background-color: rgba(138, 174, 14, 0.5);
display: none;
}
.setElement{
top:10%;
margin-left: 20%;
margin-right: 20%;
position: absolute;
border: solid 1px #000000;
background-color: rgba(138, 174, 14, 0.5);
display: none;
}
</style>
<body>
<div class="row">
<!--表单需要的原件区域开始-->
<div id="labelContext" class="col-md-3">
<!-- 样式选择开始-->
<ul class="nav nav-tabs">
<li value="0" role="presentation" class="active"><a href="#">列表</a></li>
<li value="1" role="presentation"><a href="#">单行</a></li>
</ul>
<!-- 样式选择结束-->
<div class="form-group col-sm-12">
<label class="col-sm-4 control-label text-right">文本框</label>
<div class="col-sm-8">
<input type="text" class="form-control"/>
</div>
</div>
<div class="form-group col-sm-12">
<label class="col-sm-4 control-label text-right">下拉框</label>
<div class="col-sm-8">
<select class="form-control" >
<option>-请选择-</option>
</select>
</div>
</div>
<div class="form-group col-sm-12">
<label class="col-sm-4 control-label text-right">日期框</label>
<div class="col-sm-8">
<input type="date" class="form-control"/>
</div>
</div>
<div class="form-group col-sm-12 text-right">
<label class="col-sm-4 control-label"></label>
<div class="col-sm-8">
<input type="radio"/>单选框
</div>
</div>
<div class="form-group col-sm-12 text-right">
<label class="col-sm-4 control-label"></label>
<div class="col-sm-8">
<input type="checkbox"/>多选框
</div>
</div>
<div class="form-group col-sm-12">
<label class="col-sm-4 control-label text-right">文本域</label>
<div class="col-sm-8">
<textarea class="form-control" style="height: 100px; margin-top: 5px; resize: none;"></textarea>
</div>
</div>
<!--添加标识name="panel"用于实现原件添加的作用域-->
<div class="form-group col-sm-12">
<label class="col-sm-4 control-label text-right"></label>
<div class="col-sm-8">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">面板</h3>
</div>
<div class="panel-body"></div>
</div>
</div>
</div>
<div class="form-group col-sm-12">
<label for="inputEmail3" class="col-sm-4 control-label text-right">邮件</label>
<div class="col-sm-8">
<input type="email" class="form-control" id="inputEmail3" placeholder="Email">
</div>
</div>
<div class="form-group col-sm-12">
<label for="inputPassword3" class="col-sm-4 control-label text-right">密码框</label>
<div class="col-sm-8">
<input type="password" class="form-control" id="inputPassword3" placeholder="Password">
</div>
</div>
</div>
<!--表单需要的原件区域结束-->
<!--表单的显示区域开始-->
<div id="formContext" class="col-md-9">
<form class="form-horizontal">
</form>
</div>
<!--表单的显示区域结束-->
</div>
<!--表单的设置属性区域开始-->
<div id="setPanelAttr" class="setPanel">
<span class='glyphicon glyphicon-remove' style="float: right" aria-hidden='true'></span>
<br/>
<form class="form-horizontal">
<div class="form-group col-sm-12">
<label class="col-sm-4 control-label text-right">ID</label>
<div class="col-sm-8">
<input name="id" type="text" disabled="disabled" class="form-control"/>
</div>
</div>
<div class="form-group col-sm-12">
<label class="col-sm-4 control-label text-right">数据表名</label>
<div class="col-sm-8">
<input name="table" type="text" class="form-control"/>
</div>
</div>
<div class="form-group col-sm-12">
<label class="col-sm-4 control-label text-right">面板名称</label>
<div class="col-sm-8">
<input name="name" type="text" class="form-control"/>
</div>
</div>
<div class="form-group col-sm-12">
<label class="col-sm-4 control-label text-right">排序</label>
<div class="col-sm-8">
<input name="order" type="text" class="form-control" placeholder="预留字段,功能暂时没有实现"/>
</div>
</div>
</form>
</div>
<!--表单的设置属性区域结束-->
<!--Element元件设置属性区域开始-->
<div id="setElementAttr" class="setElement">
<span class='glyphicon glyphicon-remove' style="float: right" aria-hidden='true'></span>
<br/>
<form class="form-horizontal">
<div class="form-group col-sm-12">
<label class="col-sm-4 control-label text-right">ID</label>
<div class="col-sm-8">
<input name="id" type="text" disabled="disabled" class="form-control"/>
</div>
</div>
<div class="form-group col-sm-12">
<label class="col-sm-4 control-label text-right">对应字段</label>
<div class="col-sm-8">
<input name="column" type="text" class="form-control"/>
</div>
</div>
<div class="form-group col-sm-12">
<label class="col-sm-4 control-label text-right">名称</label>
<div class="col-sm-8">
<input name="name" type="text" class="form-control"/>
</div>
</div>
<div class="form-group col-sm-12">
<label class="col-sm-4 control-label text-right">排序</label>
<div class="col-sm-8">
<input name="order" type="text" class="form-control" placeholder="预留字段,功能暂时没有实现"/>
</div>
</div>
<div class="form-group col-sm-12 text-right">
<label class="col-sm-4 control-label"></label>
<div class="col-sm-8">
<input name="required" type="checkbox"/>是否必填
</div>
</div>
<div class="form-group col-sm-12">
<label class="col-sm-4 control-label text-right">数据源</label>
<div class="col-sm-8">
<textarea name="dataSource" class="form-control" style="height: 100px; margin-top: 5px; resize: none;"></textarea>
</div>
</div>
</form>
</div>
<!--Element元件设置属性区域结束-->
</body>
<script type="text/javascript">
$(function(){
/*--------------------表单样式选项触发事件开始----------------*/
//全局样式变量:0代表列表,1代表单行
var formStyle=0;
$(".nav li").click(function () {
$(".nav li").removeClass();
$(this).addClass("active");
//设置表单样式的选项
formStyle=$(this).val();
});
/* ========表单样式选项触发事件结束========= */
//全局的原件作用域标识
var labelScope=null;
//全局标识,当前有效的panel的id
var globalPanelId=null;
//全局存放Panel的数组
var panels=[];
//全局存放Element的数组
var elements=[];
/* -------设置点击原件要添加的作用域开始---------*/
/* ==========设置点击原件要添加的作用域结束===========*/
/* -----------控制原件区域内的内容点击放到表单区域开始---------------*/
$("#labelContext .form-group").click(function(){
//将当前元素克隆处理
var label=$(this).clone();
//判断是否为面板
var panelnum=$(this).find(".panel").size();
//表单容器中是否存在一个面板
var panelJudge=$("#formContext .panel").size();
if(!panelJudge){
if(!panelnum){alert("你必须添加一个面板"); return;}
}
//设置删除图标,用于删除元件
var delIco=$("<span class='glyphicon glyphicon-remove' aria-hidden='true'></span>");
//为删除图标bind删除事件,删除父级标签
delIco.bind("click",function () {
//获取父级元素的id
var id=$(this).parent().attr("id");
if(id!="undefined" && id!=null && id!=""){
//处理Panel的数组panels的函数delPanel(id)
delPanel(id);
//删除Element元件时同时删除elements数组中的信息
delElement(id);
}
$(this).parent().remove();
});
//设置设置图标,用于触发panel属性编辑页面,或div
var setPanelIco=$("<span class='glyphicon glyphicon-wrench' aria-hidden='true'></span>");
//bind click 事件用于触发属性编辑div
setPanelIco.bind("click",function () {
//面板显示
$("#setPanelAttr").css("display","block");
//面板的id属性
var parentId=$(this).parent().attr("id");
//获取下标值
var panelIndex=parentId.substr(5,parentId.length)-1;
//将面板的属性带到设置属性的div中
var panel=panels[panelIndex];
//在设置面板属性的input中添加值
$("#setPanelAttr").find("input[name='id']").val(panel.id);
$("#setPanelAttr").find("input[name='name']").val(panel.name);
$("#setPanelAttr").find("input[name='table']").val(panel.table);
$("#setPanelAttr").find("input[name='order']").val(panel.order);
});
if(panelnum){
//对象化栅格化容器
var panelmd12=$("<div class='col-md-12'></div>");
//对面板进行处理,保证面板的显示为class=col-md-12
label.find("label").remove();
label.find(".col-sm-8").removeClass();
/* 将元件放到表单的区域中*/
$("#formContext").find("form:first").append(panelmd12.append(label).click(
function () {
//将点击的面板作为作用域,作用域为.panel-body的class属性div
labelScope=$(this).find(".panel-body");
//作用域标识
var span="<span id='labelScope' class='badge'>操作的面板</span>";
//通过span标签显示为作用域
$(".panel").find(".panel-heading").find("span").remove();
$(this).find(".panel-heading").prepend(span);
//将当前有效的panelId赋值给全局变量globalPanelId
globalPanelId=$(this).attr("id");
}));
//创建panelId参数:添加的元件panelmd12
createPanelId(panelmd12);
//触发一次panel的单击事件
panelmd12.trigger("click");
//添加删除图标
panelmd12.append(delIco);
//添加设置图标
panelmd12.append(setPanelIco);
return;
}
//设置设置图标,用于触发Element编辑页面,或div
var setElementIco=$("<span class='glyphicon glyphicon-wrench' aria-hidden='true'></span>");
//bind click 事件用于触发属性编辑div
setElementIco.bind("click",function () {
//面板显示
$("#setElementAttr").css("display","block");
//面板的id属性
var parentId=$(this).parent().attr("id");
//获取下标值
var panelIndex=parentId.substr(7,parentId.length)-1;
//将面板的属性带到设置属性的div中
var element=elements[panelIndex];
//在Element设置属性的input中添加值
$("#setElementAttr").find("input[name='id']").val(element.Id);
$("#setElementAttr").find("input[name='name']").val(element.name);
$("#setElementAttr").find("input[name='column']").val(element.column);
$("#setElementAttr").find("input[name='order']").val(element.order);
$("#setElementAttr").find("input[name='required']").val(element.required);
$("#setElementAttr").find("textarea[name='dataSource']").val(element.dataSource);
});
//判断是否为文本域
if(formStyle){
//创建栅格化容器
var md12=$("<div class='col-md-12'></div>");
//改变label选择元件的栅格化布局
label.find(".col-sm-4").addClass("col-sm-2");
label.find(".col-sm-8").addClass("col-sm-10");
label.find(".col-sm-4").removeClass("col-sm-4");
label.find(".col-sm-8").removeClass("col-sm-8");
//消除微小的差距导致无法对齐的bug
label.css("margin-left","-25px");
/* 将元件放到表单的区域中*/
labelScope.append(md12.append(label));
//创建element的ID和默认名称
createElementId(md12);
//添加删除图标
md12.append(delIco);
//添加设置图标
md12.append(setElementIco);
return;
}
//创建栅格化容器
var md6=$("<div class='col-md-6'></div>");
/* 将元素方到表单的区域中*/
labelScope.append(md6.append(label));
//将删除的图标添加到创建栅格化容器
//创建element的ID和默认名称
createElementId(md6);
md6.append(delIco);
//添加设置图标
md6.append(setElementIco);
});
/* =====================控制原件区域内的内容点击放到表单区域结束=================*/
/* ------------生成panel的id属性和Panel对象类开始--------------*/
//定义panel类
/* 参数说明:id:唯一标识;
name:显示名称;
table:对应的表;
flow:对应的模板;
order:显示顺序;
context:panel中的元件json数据*/
function Panel(id,name,table,flow,order,context){
this.id=id;
this.name=name;
this.table=table;
this.flow=flow;
this.order=order;
this.context=context;
}
//创建panelId参数:添加的元件panelmd12
function createPanelId(panelmd12) {
//为数组长度基础上默认+1,作为id和面板的区别数字
var panelsLength=panels.length+1;
//设置面板的名字
panelmd12.find("h3").text("面板"+panelsLength);
//panel添加成功后为panel指定唯一的id和设置相关默认属性
panels.push(new Panel("panel"+panelsLength,"面板"+panelsLength,"","","",""));
panelmd12.attr("id","panel"+panelsLength);
}
//处理Panel的数组panels
function delPanel(id) {
//判断是否为panel
if(id.substr(0,5)=="panel"){
//在数组中删除panel信息,但保留占位
delete panels[id.substr(5,id.length)-1];
}
}
/* =============生成panel的id属性结束================*/
/*---------------设置panel属性div的关闭事件开始--------------------*/
//面板属性设置div,在隐藏时同时将编辑的数据保存到panels数组中
$("#setPanelAttr .glyphicon-remove").click(function () {
//隐藏属性编辑div
$(this).parent().css("display","none");
//获取面板的id用于获取Panel对象存放在panels数组中的下标
var panelId=$(this).parent().find("input[name='id']").val();
var panelIndex=panelId.substr(5,panelId.length)-1;
//面板的新名称
var panelName=$(this).parent().find("input[name='name']").val();
//将编辑好的值存放到panels数组中
panels[panelIndex]=new Panel($(this).parent().find("input[name='id']").val(),
panelName,
$(this).parent().find("input[name='table']").val(),"",
$(this).parent().find("input[name='order']").val(),"");
//改变面板显示名称
$("#"+panelId).find("h3").text(panelName);
});
/* =========设置panel属性div的关闭事件结束=============*/
/* ----------设置element属性和element的id开始----------*/
/* Element是元件对象属性有:
panelId:对应面板的Id;
Id:元件的id;
column:对应数据库字段;
required:必填选项;
dataSource:元件显示的数据源;*/
function Element(panelId,Id,name,column,required,order,dataSource) {
this.panelId=panelId;
this.Id=Id;
this.name=name;
this.column=column;
this.required=required;
this.order=order;
this.dataSource=dataSource;
}
//创建element的ID和默认名称,md元件自身,labelScope元件所在的panel
function createElementId(md) {
//获取elements数组的长度,在+1的基础上作为元件的ID
var elementLength=elements.length+1;
md.attr("id","element"+elementLength);
//将Element元件的信息添加到elements数组中
elements.push(new Element(globalPanelId,"element"+elementLength,"","","","",""));
}
//删除Element元件时同时删除elements数组中的信息
function delElement(id) {
/*判断是否为element*/
if(id.substr(0,7)=="element"){
//在elements数组中删除Element信息,但保留占位
delete elements[id.substr(7,id.length)-1];
}
}
/*=======设置element属性和element的id结束========*/
/* -------------设置Element编辑div的关闭事件开始--------------*/
//面板属性设置div,在隐藏时同时将编辑的数据保存到elements数组中
$("#setElementAttr .glyphicon-remove").click(function () {
//隐藏属性编辑div
$(this).parent().css("display","none");
//获取Element的id用于获取Element对象存放在elements数组中的下标
var elementId=$(this).parent().find("input[name='id']").val();
var elementIndex=elementId.substr(7,elementId.length)-1;
//元件的新名称
var elementName=$(this).parent().find("input[name='name']").val();
//将编辑好的值存放到elements数组中
elements[elementIndex]=new Element(globalPanelId,$(this).parent().find("input[name='id']").val(),
elementName,
$(this).parent().find("input[name='column']").val(),
$(this).parent().find("input[name='required']").val(),
$(this).parent().find("input[name='order']").val(),
$(this).parent().find("textarea[name='dataSource']").val());
//改变元件显示名称
$("#"+elementId).find("h3").text(panelName);
});
/* =============设置Element编辑div的关闭事件结束===================*/
});
</script>
</html>