一个“简单”web需求引发的思考
一切从需求出发,想起曾经“坑爹”项目需求……
一个web项目需求超出环境能力那是坑人。曾经我遇到这样件事,Flex转出的swf文件因做了透明设置,在网页里输入中文时字符却跑到左上角,百思不得骑姐。最后确实是flash问题,如果不设置透明或者输入英文是没问题的,但我们那个flash是必须要透明的,且被DIV其他层挡住。没法,项目经验说了立马解决,不管你用什么方法!最终我们是很快解决了问题,坑人要求有坑人方法。
一个web项目需求超出指定实现方式那就是坑爹。比方说将军要求把敌军飞机打下来,士兵们蠢蠢欲动有拿枪的有拿炮的,但是将军突然说不能用其他武器,除了这个……,然后慢慢掏出一支鸟弓!这就是坑爹。
言归正传,我们来看一份web要求:
效果:
1、点击问题 + 号,新增一个问题(整个红色框是一个问题),点击 - 号,就删除一个问题。
2、点击答案 + 号,新增一个答案,点击 - 号,就删除那个答案。
3、在问题一上点击 + 号,新增加的问题则是在问题下展示,成为问题二。原来的问题二则变成问题三。删除问题也是同样的原理。
4、不管是在问题一上增加问题还是在问题三上增加问题还是删除问题,顺序都应该是 12345678...按顺序列下来的。
5、答案的顺序也是这样..不管是在哪个答案上点 + 号或者 - 号删除答案 ABCDEFG...都应该是按顺序列下来。
需求:
设置问题*必填的用js验证不能为空。
文本框里的的name属性只要按了 + 号的,每个问题的属性 name 都要不一样。
问题类型:单选题 多选题 主观题 选择了哪一个类型,哪一个类型下面的答案必须 js 验证不能为空。
每一个问题和上面的一样都需验证。
请原谅原文表述不清,我们自己来清理一下需求:其实就是做一份可复制的表单,技术上讲就是元素克隆,但远远没有你想象中的这么简单,这里坑多着呢。
首先需要能复制整个表单,而且是不管在哪个位置复制表单,都必须是在被点击对象的下面显示新表单。而且被复制出来的表单对应的文本应该是顺序排列(问题N,N的变化),意味着新表单及以下的表单都需要重新编号[坑1]。删除表单也是一样,被删除表单以下的表单需要重新编号。
答案的复制问题,基本跟表单一样,首先排序以ABC排序就是一个坑[坑2]意味着不能超过26个答案?
再看需求第二点是个特大的坑,input复制出来的name要求不一样!这话从何说起?后台需要接受大量连name都不知道的变量,后端的程序猿兄弟还不带刀过来闹呀[坑3]。
问题类型的单选框也是一个坑,因为radio组的名字必须不得相同才能正常使用,正常我们应该使用select或者checkbox解决的。没法,项目经验发话他想用哪就用啥[坑4]。
问题类型的单选框交互更是一个隐形大坑,点击”多选题”时需要改变它下面所有对应文字为“多选答案?”同时答案必须两个以上,如果选择“主观题”就隐藏所有答案输入框,并不需要验证答案是否为空,再点回“单选题”时,除了变文本外必须保证至少一个答案。三角关系相互扣住很是深的坑[坑5]。
解决方法:开始我是以原生javascript脚本编写。因兼容加上各种坑,用了大量脚本,还是疏忽了一个坑。今天加班没事我就用jQuery再编写了一下:
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>jQuery 实现坑爹表单</title> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript"></script> <style type="text/css"> body{ text-align: center; font: 14px "宋体"; color: #666; } form{width: 660px;margin: 20px auto;} .input{ border: 1px solid #ddd; width: 420px; height: 25px; vertical-align: middle; } ul,li{margin: 0;padding:0;list-style-type:none;} ul{ border: 2px solid red; margin: 40px 0; text-align: left; padding: 20px 0 30px; } li{line-height: 40px;} label{ display: inline-block; width: 125px; text-align: right; margin-right: 20px; } label span{color: red;} button{ border: none; vertical-align: middle; width: 17px; height: 17px; cursor: pointer; background: url("pic.jpg") no-repeat right top; margin-left: 6px\9;/*兼容IE*/ } .reduce{background-position: right -18px} .answer{height: 30px;line-height: 30px} .answer label{margin-left: 105px;} .answer .input{width: 315px;} .submit{ width: 140px; height:45px; cursor: pointer; margin-top:20px; display: inline-block; border: none; background: url("pic.jpg") no-repeat /*含提交按钮及+ -符号的图片*/ } /*css经过IE6-9\Chrome\Firefox\Safari\傲游\360\搜狗 测试*/ </style> </head> <body> <form action="#" method="post"> <ul> <li> <label><span>*</span>问题一:</label> <input type="text" class="input" name="qxname_0" /> <button type="button" class="add"></button> <button type="button" class="reduce"></button> </li> <li> <label><span>*</span>问题类型:</label> <input type="radio" name="raname_0" value="1" checked /> 单选题 <input type="radio" name="raname_0" value="2" /> 多选题 <input type="radio" name="raname_0" value="0" /> 主观题 </li> <li> <div class="answer"> <label>单选答案A:</label> <input type="text" class="input" name="answer_1" /> <button type="button" class="add"></button> <button type="button" class="reduce"></button> </div> </li> </ul> <input type="submit" class="submit" value="" /> </form> <script type="text/javascript"> $(function(){ var p_i= 1,word = "ABCDEFGHIJKLMNOPQRSTUVWXYZ",n_arr = ["零","一", "二", "三", "四", "五", "六", "七", "八", "九"],p_arr = ["","十","百","千","万"],clone =["<ul>"+$("ul").html()+"</ul>","<li>"+$("li:eq(2)").html()+"</li>"],t_arr = ["主观","单选","多选"];//定义相关变量 $("button").live("click", function(){ var c = $(this).parent().attr("class"),p = $(this).parent().parent();//获取父点击的Class与父父节点对象 $(this).index() % 2 ? (p.parent().find(c ? ".answer" : "ul").size() > 1 && p.remove()) : p.after(clone[c ? 1 : 0 ].replace(/name_\d+/g,"name_"+(++p_i))); //自动判断是否删除还是新增,新增时更新input的name以防radio冲突。 $("ul").each(function(i,item){ var n=-1;//删除或者新增后重新排序,替换文本 $("label",this).eq(0).html("<span>*</span>问题"+(i+1).toString().split("").reverse().join("").replace(/\d/g, function(k) {n++; return p_arr[n] + n_arr[k]}).split("").reverse().join("").replace(/零(千|百|十)/g, "零").replace(/(零)+/g, "零").replace(/(零)+$/g, "").replace(/一十/g,"十").replace(/二十/g,"廿")+":");//转化成中文数字 var v =$("input[name^='raname']:checked",this).val();//返回 0:主观题 1:单选题 2:多选题 $(".answer",this).each(function(i,item){ $("label",this).html(t_arr[v]+"答案"+word.charAt(i%26)+":");//因为只有26个字母,用完了又重新排序 $("input",this).attr("name",$("input",this).attr("name").replace(/answer_\d+/g,"answer_"+(i+1)));//每组答案的name都是从123456789排列 }); }); }); $("input[name^='raname']").live("click",function(){ //点击 主观|单选|多选 单选框事件 var v = $(this).val(),o = $(this).parent().nextAll();//获取值与所有答案所在的li对象 o.find("label").each(function(){ $(this).html($(this).html().replace(/主观|单选|多选/g,t_arr[v])); //对应修改文本 }); v=="0" ? o.hide() : o.show(); //判断显示还是隐藏 }); $("form").submit(function(){ var ck = true;//提交表单检查 定义变量标注是否通过审核 $("ul").each(function(i,item){ var _this = this,first = $("input:first",_this),_i = i+1;//循环所有表单检查 if(first.val()==""){ alert("第"+_i+"个问题不能为空!");//每个问题框必填 first.focus();//自动获取焦点 ck = false;//不通过 return false; }else{ var v = $("input:radio:checked",_this).val(),l = 0;//获取问题类型,和统计多少个答案 $(".answer input",_this).each(function(i,item){ if(v && $(this).val()==""){ alert("请填写第"+_i+"个问题的第"+(i+1)+"个答案!");//非主观题全部必填 $(this).focus();//自动获取焦点 ck = false;//不通过 return false; } l++;//统计答案个数 }); if(ck && v>l){ alert("第"+_i+"个问题是多选题,请多添加一个答案!"); first.focus();//自动获取焦点 ck = false;//不通过 return false; } } return ck;//判断是否跳出each() }); return ck;//返回表单是否验证成功 }) }); </script> </body> </html>
并附上使用的图片
关键词: 项目经验,需求 编辑时间: 2013-11-16 16:35:46
0
高兴0
支持0
搞笑0
不解0
谎言0
枪稿0
震惊0
无奈0
无聊0
反对0
愤怒
- 中搜索:一个“简单”web需求引发的思考
- 中搜索:一个“简单”web需求引发的思考
- 暂无评论
网友评论