2

The client wants a form in which entered numbers behave like Excel in certain ways. In particular, the data saved and the data displayed can be different, as it can in Excel. For example, the data saved could be 32425.537342 and the data displayed could be $32,425.54.

The approach we have taken to accomplish this is by using input pairs, one of type='text' and one of type='number'. The number input, which is by default hidden, stores the data to be sent and the text input displays it to the user. The number input is only displayed when the corresponding text input is focused, at which time such text input is hidden.

This following code behaves as expected in Chrome.

HTML:

<input type="text">
<input type="number">
<br>
<input type="text">
<input type="number">

jQuery:

$(document).ready(function(){
    $("[type='number']").hide();
    $("[type='text']").on("focus",function(){
        $(this).next().show().focus();
        $(this).hide();
    });
    $("[type='number']").on('blur',function(){
        $(this).prev().show();
        $(this).hide();
    });
});

Fiddle. However, in Firefox (version 33.1.1) for Mac OS, the same is not working at all. When the text input is focused on, it disappears completely, without the number input ever being displayed.

In trying to ascertain where the problem is, I cut the code back to this:

$(document).ready(function(){
    $("[type='number']").hide();
    $("[type='text']").on("focus",function(){
        $(this).next().show().focus();
        $(this).hide();
    });
});

Fiddle. This actually works as expected in both Chrome and Firefox; on focus, the text input is permanently hidden and the number input is permanently displayed.

So it seems that the issue is in the second half of the code. If you take out the $(this).hide();, the code behaves consistently in Chrome and Firefox (although not in a way that's particularly useful):

$(document).ready(function(){
    $("[type='number']").hide();
    $("[type='text']").on("focus",function(){
        $(this).next().show().focus();
        $(this).hide();
    });
    $("[type='number']").on('blur',function(){
        $(this).prev().show();
        /* $(this).hide(); */
    });
});

Fiddle. Likewise, if you remove only $(this).prev().show();, it also behaves the same in Chrome and Firefox: everything ultimately ends up hidden.

$(document).ready(function(){
    $("[type='number']").hide();
    $("[type='text']").on("focus",function(){
        $(this).next().show().focus();
        $(this).hide();
    });
    $("[type='number']").on('blur',function(){
        /* $(this).prev().show(); */
        $(this).hide();
    });
});

Fiddle. The divergence in behavior only occurs when both lines are in there; Chrome hides one input and shows the other, whereas Firefox causes everything to disappear as soon as you focus on the text input.

I thought this might be related to the Firefox focus/blur issue that makes it behave strangely in iframes (example), but taking it out of JSFiddle's iframes didn't have any effect. Fiddle in full screen here.

So how do I make the behavior in Firefox match the behavior in Chrome?

Community
  • 1
  • 1
Vincent
  • 2,689
  • 3
  • 24
  • 40
  • Possible duplicate of [Different behavior of blur event in different browsers](http://stackoverflow.com/questions/24635536/different-behavior-of-blur-event-in-different-browsers) – John Bupit Feb 20 '16 at 09:11

1 Answers1

1

This answer provided JavaScript that did the trick, and using that I was able to put together the equivalent in jQuery:

$(document).ready(function(){
    $('[type="number"]').hide();
    $('[type="text"]').on('focus',function(){
        $(this).next().show().focus();
        $(this).hide();
    });
    $('[type="number"]').on('blur',function(){
        var $this = $(this);
        setTimeout(function() {
            if(!$(document.activeElement).is($this)){
                $($this).hide();
                $($this).prev().show();
            }
        }, 0);
    });
});

Fiddle.

To quote from that answer as to why this is necessary:

[T]he issue is that different browsers choose to call event handlers in different orders. One solution is to give the other events a chance to fire by setting a timer for 0 milliseconds, and then checking the fields to see which (if any) is focused.

Community
  • 1
  • 1
Vincent
  • 2,689
  • 3
  • 24
  • 40