Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jquery Event Not Triggering for DOM Elements Created after page load [duplicate]

I have a page that trigger a calculate() function when a html5 number field is changed I have bound just about every event I can think of to it and it works for the originally loaded DOM elements.

However, if I add elements after the dom is loaded the change functions do not trigger.

I added a button that runs the calculate() function and when click it will run for the newly created elements as well as the original ones.

So I know the code works but the event isn't firing for the newly created dom elements.

Jquery Triggers

            $('.score').change(function() {
                calculate();
            });
            $('.score').bind('keyup mouseup', function() {
                calculate();
            });
            $('.score').mousewheel(function() {
                calculate();
            });
            $('.score').click(function() {
                calculate();
            });
            $('.score').keypress(function() {
                calculate();
            });

Calculate Function

function calculate() {
            $("tbody tr").each(function() {
                row_total = 0;
                $(".score", this).each(function() {
                    row_total += Number($(this).val());
                });
                $(".total", this).val(row_total);
            });
            var arr = [];
            var row = 0;
            $("tbody tr").each(function() {
                $(".total", this).each(function() {
                    arr[row] = $(this).val();
                    row += 1;
                });
            });
            var sorted = arr.slice().sort(function(a, b) {
                return b - a
            })
            var ranks = arr.slice().map(function(v) {
                return sorted.indexOf(v) + 1
            });
            row = 0;
            $("tbody tr").each(function() {
                $(".place", this).each(function() {
                    $(this).val(ranks[row]);
                    row += 1;
                });
            });
            $("tbody tr").each(function() {
                $(".place", this).each(function() {
                    var p = $(this).val();
                    switch (p) {
                        case '1':
                            $(this).css('background-color', 'gold');
                            break;
                        case '2':
                            $(this).css('background-color', 'silver');
                            break;
                        case '3':
                            $(this).css('background-color', '#8c7853');
                            break;
                        case '4':
                            $(this).css('background-color', 'white');
                            break;
                        default:
                            $(this).css('background-color', 'white');
                    }
                });
            });
        }

genRow Function

function genRow(i)
        {
            var x = "";
            for (var j = 0; j < i; j++) {
                x += '<tr class="competitors">';
                x += '<td class="row">';
                x += '<input class="name" type="text" />';
                x += '</td>';
                x += '<td class="row">';
                x += '<input class="score" type="number" step="1" min="-100" max="100" value="0" />';
                x += '</td>';
                x += '<td class="row">';
                x += '<input class="score" type="number" step="1" min="-100" max="100" value="0" />';
                x += '</td>';
                x += '<td class="row">';
                x += '<input class="score" type="number" step="1" min="-100" max="100" value="0" />';
                x += '</td>';
                x += '<td class="row">';
                x += '<input class="score" type="number" step="1" min="-100" max="100" value="0" />';
                x += '</td>';
                x += '<td class="row">';
                x += '<input class="score" type="number" step="1" min="-100" max="100" value="0" />';
                x += '</td>';
                x += '<td class="row">';
                x += '<input class="total" type="text" value="0"/>';
                x += '</td>';
                x += '<td class="row">';
                x += '<input class="place" type="text" value="0"/>';
                x += '</td>';
                x += '</tr>';
            }
            return x;
        }

HTML Code

<body>
    <table id="main">
        <tr>
            <td class="header">
                Name
            </td>
            <td class="header judge">
                Judge 1
            </td>
            <td class="header judge">
                Judge 2
            </td>
            <td class="header judge">
                Judge 3
            </td>
            <td class="header judge">
                Judge 4
            </td>
            <td class="header judge">
                Judge 5
            </td>
            <td class="header btn">
                <input id="btn_Total" type="button" value="Total"/>
            </td>
            <td class="header h_place">
                Place
            </td>
        </tr>
        <tr class="competitors">

        </tr>
        <tr>
            <td colspan="7"></td>
            <td class="header btn">
                <input id="btn_AddRow" type="button" value="Add Row"/>
            </td>
        </tr>
    </table>
</body>
like image 613
Talon06 Avatar asked Jan 20 '14 16:01

Talon06


People also ask

Which method is used to bind a callback method for an event for DOM elements added at runtime?

You can use the live() method to bind elements (even newly created ones) to events and handlers, like the onclick event. Save this answer.

Does jQuery work on dynamic content?

With jQuery, what happens is it bind event listeners on each DOM element inline and not on classes or ids. So when the binding method is called, events are bonded on the DOM loaded. To bind event on dynamically loaded DOM, we bind the event to the nearest static parent and give the element we want to bind event.

How do we bind events to elements using jQuery?

bind() method is used for attaching an event handler directly to elements. Handlers are attached to the currently selected elements in the jQuery object, so those elements must exist at the point the call to . bind() occurs.

How to bind event listener in jQuery?

Use the on() method instead. The bind() method attaches one or more event handlers for selected elements, and specifies a function to run when the event occurs.


1 Answers

Currently what you are using is called a direct binding which will only attach to element that exist on the page at the time your code makes the event binding call.

You need to use Event Delegation using .on() delegated-events approach, when generating elements dynamically or manipulation selector (like removing and adding classes).

i.e.

$(document).on('event','selector',callback_function)

Example

$(document).on('click', '.score', function(){
    //Your code
    alert("clicked me"); 
});

In place of document you should use closest static container.

The delegated events have the advantage that they can process events from descendant elements that are added to the document at a later time. By picking an element that is guaranteed to be present at the time the delegated event handler is attached, we can use delegated events to bind the click event to dynamically created elements and also to avoid the need to frequently attach and remove event handlers.

like image 73
Satpal Avatar answered Sep 28 '22 05:09

Satpal