做软件产品有时会遇到一个困惑,那就是如何样式化(格式化)用户的不规则输入。以日期/时间的输入为例,前些年比较通用的做法是写一段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的内容。
< 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的内容。
behavior : url(dateinput.htc)
}
以下是dateinput.htc的内容。
< 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 >