FireFox capture autocomplete input change event

2020-02-05 07:29发布

问题:

I'm trying to subscribe to change events on an input tag for an ajax auto complete form. These change events are not firing when the user clicks an autocomplete suggestion from FireFox.

I've seen fixes for IE, but not FireFox. You can view this behavior here

Steps to recreate: type any input in one of the boxes and click submit.

Start typing the value again in the same box.

You should see the autocomplete suggestion box appear below the input box. Notice that clicking the suggestion does not fire the change event (it also doesn't fire the click event)

Currently my only option is to disable autocomplete on this field, but I do not want to do that.

回答1:

If it makes you feel better, it is a known bug

Proposed workaround: (Not mine, from here

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Mozilla Firefox Problem</title>
<script type="text/javascript">
function fOnChange()
{
  alert('OnChange Fired');
}

var val_textBox;

function fOnFocus()
{
  val_textBox = document.getElementById('textBox').value;
}

function fOnBlur()
{
  if (val_textBox != document.getElementById('textBox').value) {
    fOnChange();
  }
}
</script>
</head>
<body>
<form name="frm">
<table>
<tr>
<td><input type="text" id="textBox" name="textBox" onFocus="fOnFocus()" onBlur="fOnBlur()"></td>
</tr>
<tr>
<td><input type="submit" value="Submit"></td>
</tr>
</form>
</body>
</html>


回答2:

Firefox 4+ fire 'oninput' event when autocomplete is used.
Here's some jQuery to make this more actionable:

$('#password').bind('input', function(){ /* your code */});


回答3:

I've had the same problem.

Apparently, there is password manager debugging available https://wiki.mozilla.org/Firefox:Password_Manager_Debugging

So I've found that for me DOMAutoComplete event got triggered and I've managed to attach it sucessfuly to a field via jQuery's bind like

$('#email').bind('DOMAutoComplete',function() { ...


回答4:

Another Suggested work around. This time using polling, you can work it in exactly the same way, checking for "changes" to your field. Tweak the poll value (default to 375ms for your own taste).

I've used jQuery and a jquery plugin someone wrote: https://github.com/cowboy/jquery-dotimeout/

Git Hub Src: https://raw.github.com/cowboy/jquery-dotimeout/master/jquery.ba-dotimeout.js

<html>
  <head>
    <meta charset="utf-8">
    <title>onChange() for Firefox / IE autofil get-around</title>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
    <script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
    <script type="text/javascript" src="/~dsloan/js/ba-dotimeout.js"></script>
    <script type="text/javascript">
        $(document).ready(function(){
            var val;
            var count=0; // used to illustrate the "poll count" 
                         // when focusing on the element and typing 
                         // (vs not focused)

            // set a focus function to poll the input
            $("#myname").focus(function() {

                // start polling
                $.doTimeout('checkname', 375, function() {
                    ++count;

                    // no changes, just exit this poll
                    if($("#myname").val() == val) {
                        return true;

                    // store the value
                    } else {
                        val = $("#myname").val();
                    }
                    var str;

                    // do stuff here with your field....
                    if($(document.activeElement) && 
                        ($(document.activeElement).attr('id') ==
                        $("#myname").attr('id'))) {

                            var len = $("#myname").val().length;
                            if(len == 0) {
                                str = 'Timer called, length 0...';
                            } else if(len < 2) {
                                str = 'Timer called, length < 2...';
                            } else {
                                str = 'Timer called, valid!';
                            }
                    }

                    // show some debugging...
                    $("#foo span").html(str+' (count: '+count+'): '+
                        $(document.activeElement).attr('id')+
                        ', val: '+$("#myname").val());

                    return true;
                });
            });

            // set a blur function to remove the poll
            $("#myname").blur(function() {
                $.doTimeout('checkname');
            });

        });
    </script>
  </head>
  <body>
    <form action="#" method=post>
        Name: <input type="text" name="name" value="" id="myname" />
        Scooby: <input name="scooby" value="" id="scooby" />
        <input type="submit" value="Press Me!" />
    </form>
    <div id="foo"><span></span></div>
  </body>
</html>


回答5:

A possibly alternative: could you simply use a timer to tell when the value of the text box changes?



回答6:

You're going to have to blur the input field and reset the focus to it. That's going to require a little trickeration though.