PDA

View Full Version : Cancel Tab key action



forum_amnesiac
04-28-2009, 02:53 PM
I am doing some testing for future development and have come across a problem

I have an HTML input form with a field that has a date mask, date validation and traps the enter key.

If the date validation is failed I reset various variables and set focus and select to the date field.

If there is another form field in the tabindex sequence then it works fine, ie focus is returned to the date field. See example at www.cognac-jaugeage.com/abctest.htm

If it is the last form field then although the variables are reset the focus is actually returned to the address bar. ie the cursor is flashing in the http address bar. See example at www.cognac-jaugeage.com/abctest1.htm

This only occurs when the Tab key is used.

I know that there will normally always be a "submit" button so that this date field should never be the last but I was wondering if this tabbing to the address bar could be stopped and focus actually given to where I have requested.

This would be useful for future testing when I haven't put in "submit" or other fields because I was only locally testing some specific field functions.

jscheuer1
04-28-2009, 04:01 PM
Generally not a good idea, the tab key isn't the method for advancing focus in all browsers, and for those that it is, users generally rely upon it. That said, have a look at this:


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script type="text/javascript">
document.onkeydown = function(e){
e = e || window.event;
var k = e.keyCode || e.which, t = e.target || e.srcElement;
if(k === 9 && t === document.forms[0].elements.whatever){
document.forms[0].elements.whatever.focus();
return false;
}
return true;
}
</script>
</head>
<body>
<form action="#">
<div>
<input type="text" name="another">
<input type="text" name="whatever">
</div>
</form>
</body>
</html>

forum_amnesiac
04-29-2009, 07:26 AM
Just to explain further, I would not want to disable the Tab key for a whole form, that I agree is not sensible.

I was just wondering if it could be trapped in my date error function, or any other, so that I could get the focus returned to where I want it.

I would immediately after this want to re-enable the Tab key, so it is in fact a function specific "ignore" of the Tab.

To further explain, I have an input field that traps the enter key onKeyDown, implements a mask onKeyPress and does date validation onBlur. The date validation is to check that the date entered is a future Monday.

In the validation script I have various error messages, dependent on what the failure was, I then pass this message to a function that alerts, and calls the focus function after a timeout. This timeout is necessary otherwise the focus fails.

It is in the focus function that I would like to trap the Tab key to get the right focus and then have the Tab key work normally immediately afterwards.

I will have a look at what you have posted and see if I can make it fit the above circumstances.

Thanks

jscheuer1
04-29-2009, 07:47 AM
Here's a simpler version that might be more to the point:


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script type="text/javascript">
function stopTab(el, e){
var k = e.keyCode || e.which;
if(k === 9){
el.focus();
return false;
}
return true;
}
</script>
</head>
<body>
<form action="#">
<div>
<input type="text" name="another">
<input type="text" name="whatever" onkeydown="return stopTab(this, event);">
</div>
</form>
</body>
</html>

forum_amnesiac
04-29-2009, 08:59 AM
Thanks again for the code

I do not want to stop the use of the Tab key for the field, it is a fairly standard user method of advancing focus in IE.

I only want to trap it if there is a problem with the date validation and I need to return focus to the date field.

The problem is that I initiate the date validation using onblur.

With onblur the 'event' is undefined so I don't know where the Tab key use is being stored.

As said previously this is not a serious problem because it is only when testing that I don't always have another tab field, but it would be nice to find a solution to this.

jscheuer1
04-29-2009, 02:18 PM
Well, try adding my code from my second post to your existing demo. Give the input both your onblur event and my onkeydown event. See what happens, you might also want to add to my function:


function stopTab(el, e){
var k = e.keyCode || e.which;
if(k === 9){
el.focus();
el.onblur();
return false;
}
return true;
}

As - it's likely that the onkeydown event, when it is tab that is pressed, will prevent the onblur event from firing.

In any case, my code will only override tab for that input, and not in all browsers, but the one exception so far (Opera) doesn't shift focus to the address bar on tab anyway. Also, consider that by using the onblur event, you've already effectively overridden tab for that field, just not in the way you wanted. If you want to fine tune it, you could add some or all of the conditions from your onblur event to the onkeydown event, such that it will not override tab when the info in the field is as required.

Another approach entirely would be using setTimeout to return focus to your element in your onblur function. That may override the default tab action - well not override it, but allow it to shift focus wherever it may go, then after the time out fires, return it to the element.

forum_amnesiac
04-30-2009, 07:36 AM
Hi John

Thanks again.

The onblur event fires fine.

This for me is an academic problem rather than a big issue, it is a 'what if' I would like to cater for.

Here is my code, the original version as opposed to the later one in which I added your suggested code.

Javascript

function fielderror(msg) {
alert(msg);
setTimeout('fieldFocus3()', 100);
return false;
}

function fieldFocus3() {
date_char=0;
jaugeage.startDate.value = "jj/mm/aaaa";
jaugeage.startDate.select();
jaugeage.startDate.focus();
return false;
}

function mondaycheck(datechosen) {
if (datechosen=="jj/mm/aaaa"){
fielderror("Veuillez écrire la date");
} else {
var dtCh= "/";
var pos1=datechosen.indexOf(dtCh);
var pos2=datechosen.indexOf(dtCh,pos1+1);
if (pos1==-1 || pos2==-1){
fielderror("Veuillez écrire la date de début comme ceci jj/mm/aaaa");
}
if (pos1!=-1 && pos2!=-1){
var parts = datechosen.split('/');
var passdate = new Date(parseFloat(parts[2]),(parseFloat(parts[1])-1),parseFloat(parts[0]),23,59,59,999);
var thisDay=passdate.getDay();
Testtoday = new Date();
if(passdate < Testtoday) {
fielderror("La date ne peut pas être plus tôt qu'aujourd'hui");
}
else {
var myDays= ["Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi","Dimanche"];
var daychosen = myDays[thisDay];
if (daychosen != "Lundi") {
fielderror("Lundi seul");
}
else {
var mondate = new Date(passdate.valueOf());
var mody = mondate.getDate();
var monmo = mondate.getMonth()+1;
var monyr = mondate.getFullYear();
if (mody < 10){ mody = '0' + mody;}
if (monmo < 10){ monmo = '0' + monmo;}
var tuedate = new Date(passdate.valueOf() + (1 * 24 * 60 * 60 * 1000));
var tudy = tuedate.getDate();
var tuemo = tuedate.getMonth()+1;
var tueyr = tuedate.getFullYear();
if (tudy < 10){ tudy = '0' + tudy;}
if (tuemo < 10){ tuemo = '0' + tuemo;}
var weddate = new Date(passdate.valueOf() + (2 * 24 * 60 * 60 * 1000));
var wddy = weddate.getDate();
var wedmo = weddate.getMonth()+1;
var wedyr = weddate.getFullYear();
if (wddy < 10){ wddy = '0' + wddy;}
if (wedmo < 10){ wedmo = '0' + wedmo;}
var thurdate = new Date(passdate.valueOf() + (3 * 24 * 60 * 60 * 1000));
var thdy = thurdate.getDate();
var thurmo = thurdate.getMonth()+1;
var thuryr = thurdate.getFullYear();
if (thdy < 10){ thdy = '0' + thdy;}
if (thurmo < 10){ thurmo = '0' + thurmo;}
var fridate = new Date(passdate.valueOf() + (4 * 24 * 60 * 60 * 1000));
var frdy = fridate.getDate();
var frimo = fridate.getMonth()+1;
var friyr = fridate.getFullYear();
if (frdy < 10){ frdy = '0' + frdy;}
if (frimo < 10){ frimo = '0' + frimo;}
/* document.getElementById('beginDate').innerHTML = mody+"/"+monmo+"/"+monyr;
document.getElementById('beginDateField').value = mody+"/"+monmo+"/"+monyr;
document.getElementById('endDate').innerHTML = frdy+"/"+frimo+"/"+friyr;
document.getElementById('FridayDate').innerHTML = frdy+"/"+frimo+"/"+friyr;
document.getElementById('endDateField').value = frdy+"/"+frimo+"/"+friyr;
document.getElementById('thursDate').innerHTML = thdy+"/"+thurmo+"/"+thuryr;
document.getElementById('thursDateField').value = thdy+"/"+thurmo+"/"+thuryr;
document.getElementById('wedsDate').innerHTML = wddy+"/"+wedmo+"/"+wedyr;
document.getElementById('wedsDateField').value = wddy+"/"+wedmo+"/"+wedyr;
document.getElementById('tuesDate').innerHTML = tudy+"/"+tuemo+"/"+tueyr;
document.getElementById('tuesDateField').value = tudy+"/"+tuemo+"/"+tueyr;
return true;*/
}
}
}
}
}

var date_char=0;
function mask(str,textbox,loc,delim){
if (date_char>7){
date_char=0;
str="";
textbox.value="";
} else if (date_char==0){
str="";
textbox.value="";
}
var masklocs = loc.split(',');
for (var i = 0; i <= masklocs.length; i++){
for (var k = 0; k <= str.length; k++){
if (k == masklocs[i]){
if (str.substring(k, k+1) != delim){
if (event.keyCode != 8){ //backspace
str = str.substring(0,k) + delim + str.substring(k,str.length);
}
}
}
}
}
if (event.keyCode != 37 && event.keyCode != 39 && event.keyCode != 46) {
textbox.value = str;
}
date_char=date_char+1;
}


and here is the HTML input line


<td align="center"><b><i>PREVISIONS DE JAUGEAGE SEMAINE DU&nbsp;&nbsp;</i></b>
<input type="text" size="12" value="jj/mm/aaaa" maxlength="12" name="startDate" tabindex="2" onKeyDown="if(event.keyCode==13) event.keyCode=9;" onKeypress="javascript:return mask(this.value,this,'2,5','/');" onblur="mondaycheck(this.value);"/>
</td>

If you try this you will see that all functions fire as expected, I have fitted your code into the functions but the 'event' does not detect the Tab using onblur.

I put the code to detect which key was pressed at the start of the mondaycheck() function and tested it, it came back as undefined.

If the enter key is pressed rather than the Tab then focus is returned as expected to the startDate field.

If there is another input field following startDate then focus 'flicks' to that before returning to startDate, this is because of the setTimeout.

So the issue only occurs when it is the Tab key used and there is no further input field.

I'm curious as to why this occurs

jscheuer1
04-30-2009, 08:39 AM
Browser quirks I would guess. A setTimeout should return focus. Have you tried increasing the amount of the timeout? Just as a test, try 1000. If that works, decrease it until you find the optimal value. But failing that, follow my other suggestion. An onblur event has no keyCode or which property, so you will have to add the onkeydown event to the input in question (in addition to the onblur event, not in place of it, and not integrated into it). You can, as I said modify its (the onkeydown) function to test for the same (or some of the same) conditions as your onblur event does in order to filter under just what circumstances that the normal tab action will be overridden.

In fact, the common tests and possibly actions could be set in a separate function to be used by either event as needed.