Event problems with FF
Made this sweet little script to auto change fields after input. Works nicely in IE, Chrome and Safari, but not in FF or opera. JS code:
function fieldChange(id, e){
var keyID = (window.event) ? event.keyCode : e.keyCode;
if (document.getElementById(id).value.length >= 2){
if (keyID >= 48 && keyID <= 57 || keyID >= 96 && keyID <= 105){
switch(id){
case "textf1":
document.getElementById("textf2").focus();
break;
case "textf2":
document.getElementById("textf3").focus();
break;
case "textf3":
if (document.getElementById(id).value.length >= 4){
document.getElementById("nubPcode").focus();
}
break;
}
}
}
HTML:
<div class="privateOrderSchema">
<input type="text" id="textf1" name="textf1"开发者_如何学C maxlength="2" size="4" onKeyUp="fieldChange('textf1')"/>-
<input type="text" id="textf2" name="textf2" maxlength="2" size="4" onKeyUp="fieldChange('textf2')" />-
<input type="text" id="textf3" name="textf3" maxlength="4" size="5" onKeyUp="fieldChange('textf3')" />
</div>
<div class="privateOrderSchema">
<input type="text" id="nubPcode" name="nubPcode" size="4" maxlength="4" />
<br />
</div>
Does anybody know how to send the "e" var in this scenario?
Tnx all :D ur gr8!
Something like the below would work, I think. It still does attach handler via the elements' attributes, which is unwanted, really. They should rather be attached via javascript.
In this attempt, you send the event
, the this
and an optional element id to the fieldChange
function. It is pretty well commented down there, but in brief, it does this:
On keyup, check the length of the element's current value. If it is equal (or greater) in length to what is set in the maxlength
, do some magic (if it is even longer, truncate the value to maxlength
). In this keyup checking, don't do anything for keycodes 9 and 16 (this allows tabbing and shift-tabbing into a "full" input element).
The "magic" is jumping to the next element. That would be either the next element in the form or the element with the id
that was optionally sent (explicitNextId
).
It is now 16 lines of js, not counting the comments. HTH.
<body>
<form action="#">
<div class="privateOrderSchema">
<input type="text" id="textf1" name="textf1" maxlength="2" size="4" onKeyUp="fieldChange(event, this)"/>-
<input type="text" id="textf2" name="textf2" maxlength="2" size="4" onKeyUp="fieldChange(event, this)" />-
<input type="text" id="textf3" name="textf3" maxlength="4" size="5" onKeyUp="fieldChange(event, this, 'nubPcode')" />
</div>
<div class="privateOrderSchema">
<input type="text" id="nubPcode" name="nubPcode" size="4" maxlength="4" />
</div>
</form>
<script type="text/javascript">
function fieldChange(event, elem, explicitNextId) {
// Obtain useable event
event = window.event ? window.event : event;
var keyCode = event.keyCode, len = elem.value.length;
// tab, shift (catches shift/tab) or small length, do nothing:
if (keyCode===9 || keyCode===16 || len < elem.maxLength) {return;}
// truncate value if exceding limit
if (len>elem.maxLength) {elem.value=elem.value.substr(0, len-1);}
// Get the next input to jump to (either from the id explicitly sent, or next in form)
var next = getNextElement(elem, explicitNextId);
// If one was found, focus it
if (next) {next.focus();}
}
function getNextElement(elem, explicitNextId) {
// From explicit id
if (typeof explicitNextId!=='undefined') {return document.getElementById(explicitNextId);}
// Get next in form
var inputs = elem.form.elements;
for (var idx=0, len=inputs.length-1, candidate; idx<len; ++idx) {
candidate = inputs.item(idx);
if (candidate===elem) {return inputs.item(idx+1);}
}
}
</script>
</body>
After the helpful comment by bobince below, I changed some indexOf
and Array/slice
stuff in the getNextElement
function to something that should work in IE too.
onKeyUp="fieldChange('textf1')"
isn't passing the event
object in the arguments. Instead:
onkeyup="fieldChange('textf1', event)"
This works both in IE (because event
refers to the global variable window.event
), and other browsers (because event
refers to the single local argument of the function you are creating with the on...
event handler attribute).
You can now drop the if (window.event)
code from the fieldChange
function, because the event will always be passed in. In places where you do need the event, it's better to sniff for the argument first before falling back to the IE version. Typically like:
function somethingHandler(event) {
event= event || window.event;
...
}
Another thing you can do to clean up the markup is use this
in the event handler:
onkeyup="fieldChange(this, event)"
now fieldChange
don't have to look up the right element by id
, since you already have a reference to it.
Better still, lose the event handler attribute and bind more unobtrusively. You can use the maxLength
property too, instead of building in the length logic about exactly when the refocus occurs. eg.:
<input type="text" name="textf1" maxlength="2" class="movetonext" />
<input type="text" name="textf2" maxlength="2" class="movetonext" />
<input type="text" name="textf3" maxlength="4" class="movetonext" />
<script type="text/javascript">
var elements= document.getElementById('myform').elements;
for (var i= elements.length; i-->0;)
if (elements[i].className==='movetonext')
elements[i].onkeyup= checkMoveToNext;
function checkMoveToNext() {
if (this.value.length>=this.maxLength) {
var elements= this.form.elements;
var ix= List_indexOf(elements, this);
ix= (ix+1)%elements.length;
elements[ix].focus();
}
}
function List_indexOf(list, item) {
for (var i= 0, n= list.length; i<n; i++)
if (list[i]===item)
return i;
return -1;
}
</script>
精彩评论