做软件产品有时会遇到一个困惑,那就是如何样式化(格式化)用户的不规则输入。以日期/时间的输入为例,前些年比较通用的做法是写一段js代码来判断用户的输入是否正确,如果不正确就提示要以某某格式录入,这种方式不仅费时费力,而且颇有马后炮之嫌。如何能够引导客户按照正确的格式填写我们所需的内容?我的看法是,可以剥夺用户手动输入的权利,只允许其在运行的范围内选择和调整。
我的初步设想是,对于一个用来进行时间输入的文本框,当鼠标移入时,如果文本框为空,则自动显示0:00这一基准时间以供调整。当鼠标指向小时部分,向上转动鼠标滚轮或按键盘的向上方向键,则小时数值增加,向下转动鼠标滚轮或按键盘的向下方向键,则小时数值增加。同样,也可以使用鼠标滚轮或者键盘方向键调整分钟数值。此外,使用键盘的左右方向键可以在小时和分钟两部分之间切换。
为此,写了一堆js代码来实现设想的功能,最终效果如下。
但是,麻烦很快就再次拜访了。为了使用这个功能,必须每次都为该文本框添加onmouseover等很多事件,太烦。怎么才能让这个功能可方便的复用?HTC应该会是个好的主意。
有关HTML Component(HTC)的介绍可参见http://www.blueidea.com/tech/web/2003/1227.asp,蓝色理想的这篇文章是我HTC入门的好导师,再此多谢了~~
使用了HTC后,页面代码得到了极大的简化,只需引用样式表dateinput.css并为需要使用时间控件的文本框指定class为dateinput即可。以下是dateinput.htm的内容。
<! DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" > < HTML > < HEAD > < TITLE > New Document </ TITLE > < link href ="dateinput.css" rel ="stylesheet" type ="text/css" > </ HEAD > < BODY > < INPUT TYPE ="text" NAME ="minute" value ="" class ="dateinput" readonly > 可以使用方向键或鼠标滚轮调整时间,呵呵 </ BODY > </ HTML >
以下是dateinput.css的内容。
.dateinput { behavior : url(dateinput.htc) }
以下是dateinput.htc的内容。
< PUBLIC:ATTACH EVENT ="onmousemove" oNEVENT ="selTime()" /> < PUBLIC:ATTACH EVENT ="onmousewheel" oNEVENT ="setTime()" /> < PUBLIC:ATTACH EVENT ="onkeydown" oNEVENT ="setTimeByKB()" /> < PUBLIC:ATTACH EVENT ="onmouseout" oNEVENT ="unselTime()" /> < PUBLIC:METHOD NAME ="regainTimeObj" /> < PUBLIC:METHOD NAME ="setObjValue" /> < script language ="javascript" > ... var h, m; var sel; var iValue; function selTime()...{ if(element.value == "") element.value = "0:00"; var bdy = document.body; regainTimeObj(); var baseLeft = bdy.leftMargin * 1 + element.offsetParent.offsetLeft * 1; var hLeft = baseLeft + h.offsetLeft * 1; var hRight = hLeft + h.boundingWidth; var mLeft = baseLeft + m.offsetLeft * 1; var mRight = mLeft + m.boundingWidth; var mouseX = window.event.clientX; if (mouseX >= hLeft && mouseX <= hRight)...{ h.select(); sel = 1; } if (mouseX >= mLeft && mouseX <= mRight)...{ m.select(); sel = 2; } } function unselTime()...{ h = null; m = null; sel = -1; } function setTime()...{ var step = parseInt(event.wheelDelta / 120, 10); switch(sel)...{ case 1: setObjValue(h, step); break; case 2: setObjValue(m, step); break; } //return false; } function setTimeByKB()...{ var kc = event.keyCode; switch(kc)...{ case 37: //left switch(sel)...{ case 2: h.select(); sel--; break; default: break; } break; case 38: //up switch(sel)...{ case 1: setObjValue(h, 1); break; case 2: setObjValue(m, 1); break; default: break; } break; case 39: //right switch(sel)...{ case 1: m.select(); sel++; break; default: break; } break; case 40: //down switch(sel)...{ case 1: setObjValue(h, -1); break; case 2: setObjValue(m, -1); break; default: break; } break; default: alert("请使用方向键或鼠标滚轮调整数字大小。"); break; } return false; } function regainTimeObj()...{ var wholeText = element.value; if(!wholeText || wholeText == "") wholeText = "0:00"; var pos = wholeText.indexOf(":"); var length = wholeText.length; h = element.createTextRange(); m = element.createTextRange(); h.moveEnd("character", pos - length); m.moveStart("character", pos + 1); switch(sel)...{ case 1: h.select(); break; case 2: m.select(); break; } } function setObjValue(obj, step)...{ iValue = parseInt(obj.text, 10) + step; var maxValue = 59; var addZero = false; switch(obj)...{ case h: maxValue = 23; addZero = false; break; case m: maxValue = 59; addZero = true; break; default: } if(iValue > maxValue) iValue = 0; if(iValue < 0) iValue = maxValue; if(addZero)...{ if(iValue.toString().length == 1) iValue = "0" + iValue; } obj.text = iValue.toString(); regainTimeObj(); } </ script >