Reputation: 92581
I am using the twitter bootstrap popovers,
In the popover I am adding a button,
I need to attach a click
handler to the button,
but the way popover works is each time it shows it removes and re-creates the element, instead of just showing/hiding it, hence removing any event handlers I have associated with said button.
I am creating several popovers all with their own version of the button, so just applying a class to the popover won't work (unless I generate a different class for each one :/), the button may or may not have it's own ID, so cannot apply an ID.
How can I apply a event handler to something in the contents of the twitter bootstrap popover?
Upvotes: 26
Views: 36299
Reputation: 353
Very simple solution that worked for me is:
// suppose that popover is defined in HTML
$('a.foo').popover();
// when popover's content is shown
$('a.foo').on('shown.bs.popover', function() {
// set what happens when user clicks on the button
$("#my-button").on('click', function(){
alert("clicked!!!");
});
});
// when popover's content is hidden
$('a.foo').on('hidden.bs.popover', function(){
// clear listeners
$("#my-button").off('click');
});
Why this works: Basically popover's content has no listener until the popover is opened.
When popover is shown, bootstrap fires its event shown.bs.popover
. We can attach an event handler on this event to $(a.foo)
using the jQuery on
method. So when popover is shown, the handler (callback) function is called. In this callback, we can attach event handlers to the content of the popover - for example: what happens when user clicks on this button inside the popover.
After popover is closed, it is good idea to remove all attached handlers to the popover's content. This is done via hidden.bs.popover
handler, which removes handlers with jQuery .off
method. This prevents event handlers inside the popover to be called twice (and more) when the popover is opened again...
Upvotes: 11
Reputation: 1048
You can get into trouble if you add more complex structure in popover's content, for example an external component. For this case, this should do the trick.
var content = $('<button>Bingo?</button>');
content.on('click', function() {
alert('Bingo!')
});
$('a.foo').popover({
html: true,
content: content
}).on('hidden.bs.popover', function() {
content.detach(); # this will remove content nicely before the popover removes it
});
Upvotes: 1
Reputation: 101
Just to slightly update DashK's very good answer: .delegate() has been superseded by .on() as of jQuery 1.7 (see here).
$('a.foo').popover({
html: true,
title: 'Hello',
placement: 'bottom',
content: '<button id="close-me">Close Me!</button>'
}).parent().on('click', 'button#close-me', function() {
console.log('World!');
});
See jsfiddle here: http://jsfiddle.net/smingers/nCKxs/2/
I have also had some issues with chaining the .on() method to $('a.foo'); if you experience such an issue, try adding it to the document, body, or html, e.g.:
$('a.foo').popover({
html: true,
title: 'Hello',
placement: 'bottom',
content: '<button id="close-me">Close Me!</button>'
});
$('body').on('click', 'button#close-me', function() {
console.log('World!');
});
Upvotes: 10
Reputation: 29341
$('.btn-popover').parent().delegate('button#close-me','click', function(){
alert('Hello');
});
If data attributes are set in static html the above method works fine. Thanks :)
Upvotes: 1
Reputation: 1
try this
var content = function() {
var button = $($.parseHTML("<button id='foo'>bar</button>"));
button.on('click', '#foo', function() {
console.log('you clicked me!');
} );
return button;
};
$( '#new_link' ).popover({
"html": true,
"content": content,
});
Upvotes: 0
Reputation: 2670
I had the same problem, and, in my case, the $(body).on('click')
workaround won't work, since the application has lotta click buttons.
I did the following instead. This way, we can limit the scope of the delegate event to just the parent of the popover element.
$('a.foo').popover({
html: true,
title: 'Hello',
placement: 'bottom',
content: '<button id="close-me">Close Me!</button>'
}).parent().delegate('button#close-me', 'click', function() {
console.log('World!');
});
JS Fiddle: http://jsfiddle.net/dashk/5Yz7z/
P.S. I used this technique in within a Backbone.View
in my application. Here's the snippet of the code in Fiddle, in case you're using this in Backbone.js
as well...: http://jsfiddle.net/dashk/PA6wY/
EDITED In Bootstrap 2.3, you can specify a target container which popover will be added to. Now, instead of doing the .parent() locator, you can also listen to events specifically to the container... This can make the listener even more specific (Imagine creating a DIV that only exists to contain the popover.)
Upvotes: 36
Reputation: 5322
This should do it. This will take care of any existing and future button elements created inside an element with the .popover class:
$('body').on('click', '.popover button', function () {
// code here
});
Upvotes: 28