简体   繁体   中英

Cloning a Bootstrap element but not all of the event listeners

In this question Cloning a bootstrap element with an event listener I asked how to clone an element without copying the bootstrap-supplied event listener. And the answer is to not pass true to the clone() command.

As it turns out, I see now that my problem is a bit more complicated than that. What I actually have is a div containing several buttons, one of which controls the expand/collapse of an associated div, and others of which provide other specialized functionality, which are provided by complex click listeners added within the javascript when creating the original. I need to keep the click() listeners on those other buttons. If I call clone() without the true argument, I lose all those listeners as well.

So is there some way I can clone(true) with listeners, but remove the bootstrap-provided cloned listener from the expand/contract button, change the IDs to be unique IDs, and then somehow still get bootstrap provide that collapse functionality (add the listener again, I guess, based on the new changed IDs in the cloned div)?

I am creating a bunch of different collapsible objects, and then cloning some of them (into another tab pane).

A simplified version of my code:

<div class="container">
  <button aria-expanded="false" data-target="#collapsible_obj_0"    data-toggle="collapse" class="btn btn-link collapsed">click here</button>
  <div style="height: 0px;" aria-expanded="false" id="collapsible_obj_0" class="collapse">
    <span>foo</span>
    <button class="btn bar-btn">bar</button>
  </div>
</div>

And a snippet from the javascript:

  $("#collapsible-obj-0 .bar-btn").click(function () {
    // do a bunch of stuff
  });

  this.collapsibleObjCounter = 15;  // really this will be one more than the number of exiting objects

  // objectContainer is the jquery object representing the top level div (passed into this method)

  var header = objectContainer.clone(true); // or not true, that is the question....
  var counter = this.collapsibleObjCounter++;
  var collapseId = "collapsible_obj_" + counter;
  header.find(".collapse").attr("id", collapseId);
  header.find("button[data-toggle='collapse']").attr("data-target", "#"+collapseId);

What I need here is to remove the event handler on the "click here" button and have bootstrap add a fresh one based on the changed IDs. If I clone without the true flag that seems to work correctly but I lose the click() functionality of the "bar" button. In reality I have a lot of "bar" buttons whose functionality I need to keep. So manually copying the click() behaviors to the cloned versions would be messy, but possible. But ideally I think what I want is a way to just remove the one event handler when I change the IDs on the collapse button and associated div, and get bootstrap to put a new one on automagically.

I apologize that this isn't runnable code - there's so much context that it's hard to pull out a streamlined runnable example.

You should try to delegate those events handlers with the use of .on() method.

$('body').on('click', '.bar-btn', someFunc);

Added a Jsfiddle with added delegated handler.

Benefits of event delegation:

  • You may not need to copy/clone those handlers at all
  • It will work just fine for the nodes added dynamically in the DOM at a later time as well (via bubbling).

So, the above code will trigger the event handler someFunc on click of bar-btn even if it is after cloning and pasting an instance of objectContainer.

To learn more, check out these links about event delegation and bubbling .

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