Results 1 to 8 of 8

Thread: Cancel Tab key action

  1. #1
    Join Date
    Apr 2009
    Location
    Cognac, France
    Posts
    400
    Thanks
    2
    Thanked 57 Times in 57 Posts

    Default Cancel Tab key action

    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.

  2. #2
    Join Date
    Mar 2005
    Location
    SE PA USA
    Posts
    30,495
    Thanks
    82
    Thanked 3,449 Times in 3,410 Posts
    Blog Entries
    12

    Default

    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:

    Code:
    <!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>
    - John
    ________________________

    Show Additional Thanks: International Rescue Committee - Donate or: The Ocean Conservancy - Donate or: PayPal - Donate

  3. #3
    Join Date
    Apr 2009
    Location
    Cognac, France
    Posts
    400
    Thanks
    2
    Thanked 57 Times in 57 Posts

    Default

    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
    Last edited by forum_amnesiac; 04-29-2009 at 07:45 AM. Reason: added further explanation

  4. #4
    Join Date
    Mar 2005
    Location
    SE PA USA
    Posts
    30,495
    Thanks
    82
    Thanked 3,449 Times in 3,410 Posts
    Blog Entries
    12

    Default

    Here's a simpler version that might be more to the point:

    Code:
    <!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>
    - John
    ________________________

    Show Additional Thanks: International Rescue Committee - Donate or: The Ocean Conservancy - Donate or: PayPal - Donate

  5. #5
    Join Date
    Apr 2009
    Location
    Cognac, France
    Posts
    400
    Thanks
    2
    Thanked 57 Times in 57 Posts

    Default

    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.

  6. #6
    Join Date
    Mar 2005
    Location
    SE PA USA
    Posts
    30,495
    Thanks
    82
    Thanked 3,449 Times in 3,410 Posts
    Blog Entries
    12

    Default

    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:

    Code:
    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.
    - John
    ________________________

    Show Additional Thanks: International Rescue Committee - Donate or: The Ocean Conservancy - Donate or: PayPal - Donate

  7. #7
    Join Date
    Apr 2009
    Location
    Cognac, France
    Posts
    400
    Thanks
    2
    Thanked 57 Times in 57 Posts

    Default

    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
    Code:
    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

    HTML Code:
    			<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

  8. #8
    Join Date
    Mar 2005
    Location
    SE PA USA
    Posts
    30,495
    Thanks
    82
    Thanked 3,449 Times in 3,410 Posts
    Blog Entries
    12

    Default

    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.
    - John
    ________________________

    Show Additional Thanks: International Rescue Committee - Donate or: The Ocean Conservancy - Donate or: PayPal - Donate

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •