简体   繁体   中英

Binding events with jQuery to multiple elements with a for loop

So I'm working on this think where I need to generate elements and then bind events to them. Every time I generate an element I unbind and rebind the events to the generated elements with a for loop. These functions seem to trigger, but they get the wrong index (which tells the code which element to work with).

Check out the code at jsFiddle http://jsfiddle.net/6UgYe/4/

Anything modular that solves this will do. Also feel free to comment on my code. I wrote most of this last year when I had just begun with javascript.

Regards,

Akke

EDIT: Here is the solution in action: http://jsfiddle.net/nwH8Z/3/ it calculates VAT-Free prices on blur.

Change your bindEmAll function to look like this -

function bindEmAll()
{
    $('#container').on('blur', 'input[id$=".5"]', function(){

     $('#Errorfield').append('Current box is ' + this.id + '<br/>').append(num_format(this.value) + '<br />')  

})
}

It makes all input boxes with IDs that end in '.5' append their ids and values, handled by your num_format() function, to #Errorfield . The event handler is attached to all input boxes inside #container , even if they are added dynamically.

And remove bindEmAll() from your click handler for #addTT ; otherwise the event handlers will be bound as many times as you've clicked addTT, which makes things quite messy ;-)

$('#addTT').click(function() {
    addTT('#container');
});

Updated fiddle here .

The problem is happening because the blur event handler is not being run until well after the loop finished. The order of execution is:

  • Attach event handler to blur event on item 1
  • Attach event handler to blur event on item 2

...some time later...

  • Actually invoke the blur event

By the time your event handler is invoked the value of the variable i from the loop has changed to the index of the last value, so that is what is being used in the event handler.

To get around this you can just put your code inside a closure:

 (function(i) {
        $('#container input#box' + i + '\\.5').unbind();
        $('#container input#box' + i + '\\.5').blur(function() {
            //error processing function;
            $('#Errorfield').append('Current box is $(\'#container input#box' + i + '\\.5\')<br />');

        });
        $('#container input#box' + i + '\\.5').blur(function() {
            $('#container input#box' + i + '\\.5').val(num_format($('#container input#box' + i + '\\.5').val()));
            $('#Errorfield').append('Current box is $(\'#container input#box' + i + '\\.5\')<br />');
        });
    })(i);

I've updated your fiddle here

  boxes = 1;

        function num_format(input) {
            //For demo purporses, we only parseInt()+5
            ret = parseFloat(input) + 5;
            return ret;
        }

        function addTT(parentElement, arg1, arg2, arg3, arg4, arg5) {

            if (!arg1) {
                arg1 = "";
            }
            if (!arg2) {
                arg2 = "";
            }
            if (!arg3) {
                arg3 = "";
            }
            if (!arg4) {
                arg4 = "";
            }
            if (!arg5) {
                arg5 = num_format((0.00).toFixed(2));
            }


            row = $('<tr></tr>').attr('id', boxes);

            cell1 = $('<td class="inputcell"></td>');
            cell2 = $('<td class="inputcell"></td>');
            cell3 = $('<td class="inputcell"></td>');
            cell4 = $('<td class="inputcell"></td>');
            cell5 = $('<td class="inputcell"></td>');

            input1 = $('<input></input>').attr('style', 'width:100px;').attr('id', 'box' + boxes + '.1').attr('name', 'box' + boxes + '_1').attr('type', 'text').attr('value', arg1);
            input2 = $('<input></input>').attr('style', 'width:100px;').attr('id', 'box' + boxes + '.2').attr('name', 'box' + boxes + '_2').attr('type', 'text').attr('value', arg2);
            input3 = $('<input></input>').attr('style', 'width:93px;').attr('id', 'box' + boxes + '.3').attr('name', 'box' + boxes + '_3').attr('type', 'text').attr('value', arg3);
            input4 = $('<input></input>').attr('style', 'width:149px;').attr('id', 'box' + boxes + '.4').attr('name', 'box' + boxes + '_4').attr('type', 'text').attr('value', arg4);
            input5 = $('<input></input>').attr('style', 'width:90px;').attr('id', 'box' + boxes + '.5').attr('name', 'box' + boxes + '_5').attr('type', 'text').attr('value', arg5);

            $(cell1).append(input1);
            $(cell2).append(input2);
            $(cell3).append(input3);
            $(cell4).append(input4);
            $(cell5).append(input5);

            $(row).append(cell1);
            $(row).append(cell2);
            $(row).append(cell3);
            $(row).append(cell4);
            $(row).append(cell5);

            $('#tBoxes').append(row);
            boxes++;
        }

        function subTT(parentElement) {
            boxes = boxes - 1;
            $(parentElement + ' #' + boxes).hide(0, function () {
                $(parentElement + ' #' + boxes).remove();
            }
            );
        }
        function bindEmAll() {
            alert(boxes);
            for (var i = 1; i <= boxes - 1; i++) {

                $('#container input#box' + i + '\\.5').blur(function () {
                    alert($(this).val());
                    $(this).val(num_format($(this).val()));
                    //$('#container input#box' + i + '\\.5').val(num_format($('#container input#box' + i + '\\.5').val()));
                    //$('#Errorfield').append('Current box is $(\'#container input#box' + i + '\\.5\')<br />');
                });
            }
        }
        $('#addTT').click(function () {
            addTT('#container');
            bindEmAll();
        });
        $('#subTT').click(function () {
            subTT('#container');
        });
        $(function () { addTT('#container'); bindEmAll(); });

Here is a small example of adding new elements and process their events:

<button id="add">+</button>
<button id="remove">-</button>
<div id="holder">

</div>

.

$('#add').on('click', function () {
    $('#holder').append('<p>click me!</p>');
});

$('#remove').on('click', function () {
    $('#holder p:last-of-type').remove();
});

$('#holder').on('click', 'p', function () {
    alert('my id is: ' + $('#holder p').index(this));
});

And you can check it out here: http://jsfiddle.net/simo/PyKDz/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM