6

The following code is intended to check if 4 numbers are entered in the blurred field. If not, the field value is deleted, and the field is focused. The deletion works fine, but the the call to focus() does not work.

$('input.dateValue').live('blur',function(event){
  if (!(/(\d){4}$/.test($(this).attr('value')))) $(this).attr('value','').focus();
});

Why does the call to focus() not focus the field?

Lion
  • 18,729
  • 22
  • 80
  • 110
jela
  • 1,449
  • 3
  • 23
  • 30
  • Are you sure your function really gets executed? Add `alert("test");` just before the `if` statement. That way you'll get an message on your screen whenever the function is executed. – Jocelyn Jul 08 '12 at 03:16
  • @Jocelyn the regex does work (on blur, it does delete any value that is not four digits), so that part of the chain gets executed, but the focus() part does not. – jela Jul 08 '12 at 03:17
  • Note that your regex is testing for 4 digits at the end of the field. (E.g., "asdf1234" would pass.) Make it `/^\d{4}$/` if you want 4 digits and nothing else. – nnnnnn Jul 08 '12 at 03:23
  • When I [tried it](http://jsfiddle.net/DAEsK/) in Chrome I noticed that it _does_ set the focus back _if_ I tab forward or backwards to another input but not if I click on the document or tab forwards out of the last field. Weird. – nnnnnn Jul 08 '12 at 03:29
  • @nnnnnn interesting, in Firefox it does not work, but in Chrome it does work. – jela Jul 08 '12 at 03:31

5 Answers5

18

Since the blur event fires before the actual loss of focus, you cannot use .focus() right away. You have to push it down the stack, so that it executes after the input has lost focus. Put your .focus() in a timer (no delay necessary):

$('input.dateValue').on('blur', function(event)
{
    if ( ! /(\d){4}$/.test(this.value) )
    {
        var $this = $(this).val('');

        setTimeout(function (){
            $this.focus();
        }, 0);
    };
});​

Here's the fiddle: http://jsfiddle.net/TdfFs/


Update: to demonstrate that this does work in Chrome, I made another fiddle: http://jsfiddle.net/TdfFs/1/

Joseph Silber
  • 214,931
  • 59
  • 362
  • 292
  • 1
    I tried your demo in Chrome, and when I press tab from that field the focus moves to the address bar and stays there. – nnnnnn Jul 08 '12 at 03:33
  • @nnnnnn - In the demo - since there's no other field to focus on - pressing `tab` takes you out of the window context, where Javascript's reign is gone. If there are other focus-able elements on the page, [my code sure does work](http://jsfiddle.net/TdfFs/1/). – Joseph Silber Jul 08 '12 at 03:37
  • You beat me to this, it's interesting to note that the alternatives only seem to fail in Chrome. – Korvin Szanto Jul 08 '12 at 03:38
1

Demo http://jsfiddle.net/dsaSX/3/

Try using this.value instead of $(this).attr(...)

Rest hope this helps the cause, :)

Oh and I have used .on event if you are using Jquery 1.7 and above.

Read this: What's the difference between jQuery .val() and .attr('value')?

Read here http://forum.jquery.com/topic/jquery-focus-after-blur

And another Known Forum Solution with SetTimeOut http://forum.jquery.com/topic/focus-inside-a-blur-handler see post below

code

$('input.dateValue').on('blur', function(event) {

    if (!(/(\d){4}$/.test(this.value))) {

        $(this).val('').focus();
    };
});​
Community
  • 1
  • 1
Tats_innit
  • 33,991
  • 10
  • 71
  • 77
  • Why `$(this).attr('value', '')`? Why not simply `$(this).val('')`? – Joseph Silber Jul 08 '12 at 03:25
  • When I try the demo, typing in 'asdf', it deletes it but the field still is not focused (ie I cannot type in the field without refocusing it manually) – jela Jul 08 '12 at 03:26
  • @JosephSilber indeed Will update soon, although I will flick you a subtle difference as well, thanks `:)` – Tats_innit Jul 08 '12 at 03:27
  • @JosephSilber I am just learning jquery and I do not know the best way. Is it better to use $(this).val('')? – jela Jul 08 '12 at 03:28
  • @jela see here: http://stackoverflow.com/questions/4837133/whats-the-difference-bewteen-jquery-val-and-attrvalue `:)` – Tats_innit Jul 08 '12 at 03:30
0

Instead of blur use focusout

http://jsfiddle.net/fedmich/aKY9f/


Tips:

Indent your codes

Instead of attr, value use $.val('')

on using IF(), use brakets please {}

Write cleaner, simple as possible so you dont get confused later.

Happy Coding :)

fedmich
  • 5,343
  • 3
  • 37
  • 52
  • 1
    That doesn't make any difference for me. Both blur and focusout work if you try to set focus to another field, but if you click on the document or if it is the last field (such that tabbing moves focus up to the address bar) then they don't work. – nnnnnn Jul 08 '12 at 03:31
  • You could use the e.preventDefault(); on your case – fedmich Jul 08 '12 at 03:35
0

Little detail,

Most of the time I read such problem. It is often because the event is not correct. Be sure that your page is processed before asking the system to set the focus on something.

Here an example where the event pageshow is a better place than pagebeforeshow

DOES NOT WORK LIKE THIS

/**
 *** a hook to handle list drawing. DOES NOT WORK**
 */
$(document).delegate('#dropdownPopupWindow', "pagebeforeshow", function() {
    console.log(UIPopup.TAG+"pagebeforeshow on popup dropdownPopupWindow is setting focus on field field_dropdown_label");
    $('#field_dropdown_label').focus();
});

WORK LIKE THIS

/**
 *** a hook to handle list drawing.**
 */
$(document).delegate('#dropdownPopupWindow', "pageshow", function() {
    console.log(UIPopup.TAG+"pageshow on popup dropdownPopupWindow is setting focus on field field_dropdown_label");
    $('#field_dropdown_label').focus();
});
0

If you're using Bootstrap modals, this does not work:

$('#modalID').modal('show');
$('#modalID #fieldID').focus();

because it takes a bit for the modal to be drawn and to be available for focusing... I have found that a timeout of 400ms is fast enough that users won't be affected and slow enough that it always focuses on the element.

$('#modalID').modal('show');
setTimeout(function(){  $('#modalID #fieldID').focus(); }, 400);

And actually it wouldn't hurt to use executable comments:

function wait_for_modal_to_be_drawn_then( fn )
{
  setTimeout( fn, 400 );
}

$('#modalID').modal('show');
wait_for_modal_to_draw_then( 
     function(){  $('#modalID #fieldID').focus(); } 
);
MustModify
  • 657
  • 10
  • 20