jqueryfirefoxjquery-eventspromptmousedown

Why does this variable prompt in my jQuery function work in Chrome but not Firefox?


I'm running into this quirk between how Chrome and Firefox execute this function, but I can't figure out why Firefox won't execute. I have checkboxes for which a function listens for any change in any checkbox, then executes some text to appear. But, for one checkbox, I would like to interrupt the usual text and do some regex on it before completion. So, I have a mousedown event listener which tries to gain this effect. My rationale is that the mousedown will execute code before the checkbox change event (not sure if this is true across all browsers).

The weirdness arises when during this mousedown function, a variable called amt requires a value. If the variable amt is entered through a prompt dialog, Firefox will not execute the rest of the function. If, instead, the same variable amt is entered through an <input> element instead, the function works fine. In Chrome, the same results are achieved with either method.

Can someone please explain the difference and whether there is a better way to "halt" a function so another function can run before completion?

A fiddle here: http://jsfiddle.net/ufgvoghw/7/

JS

dxOuts = {
    dxOut100: 'ITEM #0:',
    dxOut101: 'ITEM #1:',
    dxOut102: 'ITEM #2: '
};
var final = '';
var sel = null;

$('#_box0').mousedown(function () {
    $('#dxOut100').prop('disabled', true); // <-- disable checkbox to ensure click event doesn't take place when label mousedown occurs
   //  var amt = prompt('Enter amount'); //<-- this doesn't work in firefox, but works in chrome
    var amt = $('#amt').val(); //<-- this works in FF and chrome
    dxOuts.dxOut100 = dxOuts.dxOut100.replace(/#[\d*(?=\d)]/, '#'+amt);
    $('#dxOut100').prop('disabled', false).trigger('click');
});
function printf(){
    final += dxOuts[sel] + '\n\n';
    $('#output').val(final);
}

$('input:checkbox').on('change', function () {
    if($(this).is(':checked')){
    sel = $(this).attr('id');
    printf();

    }
});

HTML

<label id="_box0">
    <input type='checkbox' id='dxOut100'>ITEM #</label>
<input id="amt" size=5>
<br>
<label id="_box1">
    <input type='checkbox' id='dxOut101'>ITEM #1</label>
<br>
<label id="_box2">
    <input type='checkbox' id='dxOut102'>ITEM #2</label>
<br>
<br>
<textarea id='output' cols=25 rows=5></textarea>

Solution

  • Actually, the code below prompt is being executed as expected. The problem is the prompt prevents the default change event for the checkbox to occur. So the string is not added to the end of output.

    Why so hard?

    If you want separate change event logic for first checkbox, just do it, and move the common code to separate function:

    Fiddle

    var dxOuts = {
        dxOut100: 'ITEM #0:',
        dxOut101: 'ITEM #1:',
        dxOut102: 'ITEM #2: '
    };
    var final = '';
    var sel = null;
    
    function printf(){
        final += dxOuts[sel] + '\n\n';
        $('#output').val(final);
    }
    
    //common code to call for all checkboxes
    function checkboxCnahged(e) {
        var checkBox = $(e.target);
    
        if(checkBox.is(':checked')){
            sel = checkBox.attr('id');
            printf();
        }
    }
    
    $('#dxOut100').change(function (e) {
        if ($(e.target).is(':checked')) { // show prompt only if checked
            var amt = prompt('Enter amount'); // <-- now this works
            //var amt = $('#amt').val(); //<-- this works in FF and chrome
            console.log(amt);
            dxOuts.dxOut100 = dxOuts.dxOut100.replace(/#\d*/, '#' + amt); //fixed the regex to replace the whole number, not only the first digit
        }
        checkboxCnahged.apply(this, arguments);
    });
    
    $('input:checkbox:not(#dxOut100)').on('change', function () {
        checkboxCnahged.apply(this, arguments);
    });
    

    And shorter version with one change handler:

    Fiddle

    var dxOuts = {
        dxOut100: 'ITEM #0:',
        dxOut101: 'ITEM #1:',
        dxOut102: 'ITEM #2: '
    };
    var final = '';
    var sel = null;
    
    function printf(){
        final += dxOuts[sel] + '\n\n';
        $('#output').val(final);
    }
    
    $('input:checkbox').change(function (e) {
        if ($(e.target).is(':checked')) { // show prompt only if checked
            if (e.target.id === 'dxOut100') {
              var amt = prompt('Enter amount'); // <-- now this works
              dxOuts.dxOut100 = dxOuts.dxOut100.replace(/#\d*/, '#' + amt); 
            }
    
            sel = e.target.id;
            printf();
        }
    });