前几天优化之前做过的一个用户注册页面,发现这种表单从布局到各个表单项的验证提示,重复性很强,想着可以做成一个模板,日后再有此类需求直接拿来修改一下就可以了。
一、UI设计
布局:每一个表单项都由项名、项值、填写/验证提示这三部分组成,在布局上是一个三列多行的表格结构。
交互:表单初始化时显示各表单项的填写提示;表单项blur时验证该项并验证提示;表单项focus时还原该项填写提示;submit时验证所有表单项并验证提示。
二、关键部分实现
布局实现:考虑到表格布局以及各表单项的垂直居中需求,用<table>是最合适的,每行两个td,左为项名,右为项值,提示div在项值td中并且position:absolute。但是实际操作中,提示div相对项值td垂直居中的需求在IE9中始终存在兼容性问题,只好放弃table。不考虑html语义化的基础上全部采用<div>。
验证实现:通过在表单项中添加required、pattern属性,并在表单初始化时绑定验证事件,实现对改表单项的必填、正则验证。
三、Demo
http://youryida.duapp.com/demo_front/registerFormTemplate.html 浏览器支持 ie9+
<!doctype html>
<html>
<head>
<title>注册表单模板</title>
<meta http-equiv="X-UA-Compatible" content="IE=9">
<meta charset="utf-8" />
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-condivol" content="no-cache, must-revalidate">
<meta http-equiv="expires" content="0">
<style>
*{padding:0;margin:0;font-family: 'Microsoft Yahei';}
#formTable{margin: 10px auto;width:400px;}
.formItem{font-size:14px;text-align:center;height:25px;margin:20px 0;}
.labelBox{float:left;width:50px;text-align:right;padding-right:10px;position:relative;line-height:30px;}
.labelBox:after{content:":";}
.contBox{float:left;width:300px;height:100%;text-align:left;position:relative;}
.contNoInput{border-bottom:1px solid #ccc;text-align:center;}
.contBox input[type="text"],.contBox input[type="password"]{width:100%;height:100%;}
.lineTip{position: absolute;left: 300px;top:50%;width: 300px;font-size:12px;line-height: 25px;margin-top:-10px;margin-left:8px;color: #666;text-align:left;}
.warnTip{color:red;}
</style>
<script src="jq1.7.2.js"></script>
<script type="text/javascript">
$(function(){
tipInit();
focusChkBind();
submitBind();
});
//初始化表单项填写说明
function tipInit(){
$('.contBox').each(function(){
var tip=$(this).attr("lineTip");
if (!tip) tip="";
$(this).append('<div class="lineTip">'+tip+'</div>');
});
}
//得失焦点变换提示
function focusChkBind(){
$("input[type=text],input[type=password]").blur(function(){
inputOneChk($(this));
});
$("input[type=text],input[type=password]").focus(function(){
var contBox=$(this).parent();
var tip=contBox.attr("lineTip");
contBox.find(".lineTip").removeClass("warnTip").html(tip);
});
}
//非空和正则验证
function inputOneChk(oInput){
var val=oInput.val().trim();
var required=oInput.attr("required");
var pattern=oInput.attr("pattern");
var patternTip=oInput.attr("patternTip");
if (!patternTip) patternTip="填写内容不符合要求!";
var oTip=oInput.parent().find(".lineTip");
if(required && val==''){
oTip.addClass("warnTip").html("不能为空!");
return;
}
if(pattern){
var reg = new RegExp(pattern);
if(! reg.test(val)){
oTip.addClass("warnTip").html(patternTip);
return;
}
}
oTip.html("<div style='font: bold 16px "黑体";color:#fff;border-radius:9px; 18px;height:18px;background:#58AB2F;line-height: 21px;margin-top:4px;'>√</div>");
}
//提交按钮验证
function submitBind(){
$("#submit").click(function(){
$("input[type=text],input[type=password]").each(function(){
inputOneChk($(this));
});
//otherChk();
if($(".warnTip").length>0) return false;
alert("验证通过,开始提交");
});
}
</script>
</head>
<body>
<form id="formTable">
<div class="formItem" style="height: 130px;">
<div class="labelBox" style="margin-top:60px;">头像</div>
<div class="contBox contNoInput" lineTip="图片应小于2M">
<div id="cont_avatar" style="height: 128px;128px;background-color: #eee;margin-left:80px;"></div>
</div>
</div>
<div class="formItem">
<div class="labelBox">姓名</div>
<div class="contBox" lineTip="填写真实姓名">
<input type="text" id="name" required />
</div>
</div>
<div class="formItem">
<div class="labelBox">昵称</div>
<div class="contBox" lineTip="昵称为字母数字下划线组合,不可为汉字">
<input type="text" id="nickName" required pattern="^w{3,15}$" patternTip="昵称应为3-15位的字母数字下划线组成!"/>
</div>
</div>
<input type="button" value="提 交" id="submit" style="80px;height:35px;font-size:14px;margin:5px auto;display: block;"/>
</form>
</body>
</html>