Jquery clone div breaking events

BRBT

I am cloning a div and changing all of the child element id's and appending it below the original div. Now within that div I have several buttons that trigger events when clicked. Each one of these buttons have a class name that I am using to fire the event opposed to using the id. However when I try to click on any buttons within my cloned div none of my events are firing.

Here is how I am cloning my div, changing the id's and appending it:

$(function() {    
  var $section = $("#facility_section_info").clone();
  var $cloneID = 1; 
    $( ".addSection" ).click(function() { 
        var $sectionClone = $section.clone(true).find("*[id]").andSelf().each(function() { $(this).attr("id", $(this).attr("id") + $cloneID); });
        $('#facility_section_info').append($sectionClone);
        $cloneID++; 
    });
});

here is an original uncloned button within the div that fires an event.

<input type="button" value="+" id="addRows" class="addRows"/>

And here is what the cloned button looks like:

<input type="button" value="+" id="addRows1" class="addRows">

The only thing that has changed is that I have added a 1 at the end of the id.

Here is the event that gets fired when this button gets clicked:

$(function() {
    var $componentTB = $("#component_tb"),
        $firstTRCopy = $("#row0").clone();
        $idVal = 1;
    $(".addRows").click(function() {
        var copy = $firstTRCopy.clone();
        var newId = 'row' +$idVal;
        copy.attr('id', newId);
        $idVal += 1;
        copy.children('td').last().append("<a href=\"javascript:remove('" + newId + "')\">Remove</a>");
        $componentTB.append(copy);
    });
});

All this function does is clone a table row in its original form and append it to the end of a table with an added remove link. This function works exactly how I need it to other than not firing when I click on my cloned button.

Why do my cloned buttons not fire any of my events that are called by class name and not id?

SpYk3HH

Easiest answer; the clone isn't breaking the event. The event isn't firing because it's never assigned to the new element. What you're doing when you clone the element is creating a dynamic element. This means it's added to the DOM after the page has loaded, at which point, your event was already delegated.

The way you're delegating the event is not wrong. It's simply not the best practice when you will have dynamic elements. There are a few ways you can handle this.

Using .clone()'s withDataAndEvents parameter.

The withDataAndEvents parameter of .clone() is intended to make this process easier by copying data and events to the new element, as such

var copy = $firstTRCopy.clone(true)

However, this can have a few nasty side-effects. For instance, it's been known to clone id's and if your event is assigned to an id, you'll still only get fire on the first element.

Event Delegation - See Understanding Event Delegation

This is a method by which we use a parent element, or even the document root Object to attach events that will always be fired on all children. Such as:

$(document).on('click', '.addRow', function(e) {...})

Due to convenience more than anything, it's often not recommended you attach to the document root. I had first suggested it because I was in public and it was a quick and easy answer. It's not unsafe to attach to the document root, but can become an issue if you have a lot going on in your page. See, each element an event is assigned to will bubble up when the event is fired. Simply put, when you attach 'click' to an element with an event delegated via the document, you're essentially clicking the entire DOM. More often than not, it's not really an issue and I make use of it all day long for convenience of readability.

However, the more proper way would be to look for the closest parent element that exist on load. That is to say, it is not created dynamically. Simply put, like so:

    $('#parentAlreadyLoaded').on('click', '.addRow', function(e) {...})

Note: Assigning an event to .addRow using $(document) or $('parent element selector') does not change the event parameter in function(e) {. The e in $('.addRow').click is the same as the e in $(document OR 'parent').on('click', '.addRow'

Short Example

function addRow(e) {
    if (console && console['log']) console.log(e);
	var par = $('#addRows'),
		tr = $('<tr />').appendTo(par),
		tdBlue = $('<td />').appendTo(tr),
		tdRed = $('<td />').appendTo(tr),
		btnBlue = $('<button />', { 'class': 'make-blue', 'text': 'Make Blue' }).appendTo(tdBlue),
		btnRed = $('<button />', { 'class': 'make-red', 'text': 'Make Red' }).appendTo(tdRed)
}

$(function() {
	$('thead button').on('click', addRow);
	$('#addRows').on('click', '.make-blue', function(e) {
        if (console && console['log']) console.log(e);
		$(this).closest('tr').removeClass('red').addClass('blue');
	});
	$(document).on('click', '.make-red', function(e) {
        if (console && console['log']) console.log(e);
		$(this).closest('tr').removeClass('blue').addClass('red');
	});
})
table { border-collapse: collapse; margin: 0 auto; }
tr { padding: .25em .5em; text-align: center; }
th, td { border: 3px groove; }
th button { margin: .25em auto; }
td button { margin: .5em; }
.blue { background-color: #00F; }
.red { background-color: #F00; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<table>
    <thead>
        <th colspan="2">
            <button>Click Me</button>
        </th>
    </thead>
    <tbody id="addRows"></tbody>
</table>

Also

Making use of $(document).on, as aforementioned is handy for readability. For example, If I have a simple page, with 20 or less events and none are really overlapping, then I'll use it to assign events as such:

$(document)
    .on('event', 'selector1', function(e) { /*  do Work */ })
    .on('differentEvent', 'selector1', function(e) { /* do Work */ })
    .on('event', 'selector2', function(e) { /*  do Work */ })
    .on('event', 'selector3', function(e) { /*  do Work */ })
    .on('differentEvent', 'selector3', function(e) { /* do Work */ })
    .on('differentEvent2', 'selector3', function(e) { /*    do Work */ })

This is possible due to jQuery's chainability. Just be careful doing this as you made to use e.stopPropagation() to prevent bubbling.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

clone div using jquery

From Dev

clone div using jquery

From Dev

Div tag events in jquery

From Dev

Div tag events in jquery

From Dev

jQuery .clone(true, true) not cloning events

From Dev

Jquery clone div inside form

From Dev

Clone HTML DIV with jQuery on select

From Dev

clone div with jquery and show as code

From Dev

Hide div initially in jquery clone

From Dev

jquery clone div for the first time

From Dev

Clone a div in another div using jQuery

From Dev

jQuery events to new created div

From Dev

How do I clone element events excluding data in jQuery?

From Dev

How do I clone element events excluding data in jQuery?

From Dev

jquery clone div into variable and remove style attribute

From Dev

jQuery auto rename the selectors in clone div

From Dev

Jquery clone a div with inputs fields(and relative values)

From Dev

jQuery UI Draggable Clone in Scrollable DIV

From Dev

clone another div that time jquery not work

From Dev

Javascript Clone Objects with Events

From Dev

Jquery clone method to clone mutliple (more than one) div's (not a single div multiple times) inside a page

From Dev

How to copy and paste a div with jQuery's clone() function?

From Dev

jQuery clone an image with a class of active and set it as background image of a div

From Dev

clone img src to use as a div background via jquery

From Dev

Jquery Clone, Changed value is not persist on the cloned object (div)

From Dev

jquery - clone td, prepend, and change new td to div

From Dev

Clone a form input as a jQuery Object And Display it with wrap div / li

From Dev

jQuery clone an image with a class of active and set it as background image of a div

From Dev

JQuery / Javascript Draggable and Resizable don't work with a div clone

Related Related

  1. 1

    clone div using jquery

  2. 2

    clone div using jquery

  3. 3

    Div tag events in jquery

  4. 4

    Div tag events in jquery

  5. 5

    jQuery .clone(true, true) not cloning events

  6. 6

    Jquery clone div inside form

  7. 7

    Clone HTML DIV with jQuery on select

  8. 8

    clone div with jquery and show as code

  9. 9

    Hide div initially in jquery clone

  10. 10

    jquery clone div for the first time

  11. 11

    Clone a div in another div using jQuery

  12. 12

    jQuery events to new created div

  13. 13

    How do I clone element events excluding data in jQuery?

  14. 14

    How do I clone element events excluding data in jQuery?

  15. 15

    jquery clone div into variable and remove style attribute

  16. 16

    jQuery auto rename the selectors in clone div

  17. 17

    Jquery clone a div with inputs fields(and relative values)

  18. 18

    jQuery UI Draggable Clone in Scrollable DIV

  19. 19

    clone another div that time jquery not work

  20. 20

    Javascript Clone Objects with Events

  21. 21

    Jquery clone method to clone mutliple (more than one) div's (not a single div multiple times) inside a page

  22. 22

    How to copy and paste a div with jQuery's clone() function?

  23. 23

    jQuery clone an image with a class of active and set it as background image of a div

  24. 24

    clone img src to use as a div background via jquery

  25. 25

    Jquery Clone, Changed value is not persist on the cloned object (div)

  26. 26

    jquery - clone td, prepend, and change new td to div

  27. 27

    Clone a form input as a jQuery Object And Display it with wrap div / li

  28. 28

    jQuery clone an image with a class of active and set it as background image of a div

  29. 29

    JQuery / Javascript Draggable and Resizable don't work with a div clone

HotTag

Archive