Dan Dan - 4 months ago 8
Javascript Question

Updating the values of variables in jQuery

I have a relatively simple script for manipulating the text in two fields. This works great initially but when I click on the button

#check
the values of
$field1
and
$field2
don't seem to update. This means that whilst the script can manipulate the second field when text is inputted in the first field, it cannot manipulate the first field when text is inputted in the second field.

$(document).ready(function() {
var val = "";
$field1 = $("#password");
$field2 = $("#fake-password");

$('#check').click(function() {
$field1 = $("#fake-password");
$field2 = $("#password");
$("#password").hide();
$('#check').hide();
$("#fake-password").show().focus();
$('#check-inv').show();
});

$('#check-inv').click(function() {
$field1 = $("#password");
$field2 = $("#fake-password");
$("#fake-password").hide();
$('#check-inv').hide();
$("#password").show().focus();
$('#check').show();
});

$(function () {
$field1.on('keydown', function () {
setTimeout(function () {
$field2.html($field1.val());
val = $field1.val();
$field2.val(val);
}, 0);
});
});
});


I apologise if this is an obvious mistake as I am relatively new to the language but I would appreciate any help in fixing this problem.

Answer

This code runs immediately on ready:

$(function () {
    $field1.on('keydown', function () {
        setTimeout(function () {
            $field2.html($field1.val());
            val = $field1.val();
            $field2.val(val);
        }, 0);
    });
});

It uses the then-current value of $field1, and so hooks the event on the #password field.

Your best bet is probably to hook the event to both fields; within the handler body, the value of $field1 and $field2 as of when the event runs will be as you expect. So:

$field1.add($field2).on('keydown', function () {

Also note that $(function() { }) is a shortcut for hooking up a ready handler. Since that code is already inside a ready handler, there's no need to wrap it again.

Combining that with the suggestion above (and declaring $field1 and $field2 so we don't fall prey to The Horror of Implicit Globals), we get (see ** comments):

$(document).ready(function() {
    var val = "";
    var $field1 = $("#password");                     // **
    var $field2 = $("#fake-password");                // **

    $('#check').click(function() {
        $field1 = $("#fake-password");
        $field2 = $("#password");
        $("#password").hide();
        $('#check').hide();
        $("#fake-password").show().focus();
        $('#check-inv').show();
    });

    $('#check-inv').click(function() {
        $field1 = $("#password");
        $field2 = $("#fake-password");
        $("#fake-password").hide();
        $('#check-inv').hide();
        $("#password").show().focus();
        $('#check').show();
    });

    // ** Note no $(function() { }) wrapper:
    $field1.add($field2).on('keydown', function () {  // **
        setTimeout(function () {
            $field2.html($field1.val());
            val = $field1.val();
            $field2.val(val);
        }, 0);
    });
});
Comments