在 Twitter Bootstrap 弹出框中为按钮附加事件处理程序

26

我正在使用 Twitter Bootstrap 弹出框。

在弹出框里,我添加了一个按钮。

我需要给这个按钮附加一个 click 事件处理程序,但是弹出框的工作方式是每次显示时都删除并重新创建元素,而不仅仅是显示/隐藏它,因此会删除任何与该按钮相关联的事件处理程序。

我正在创建多个弹出框,每个弹出框都有自己版本的按钮,因此仅将类应用于弹出框不起作用(除非为每个弹出框生成不同的类),按钮可能有自己的 ID,因此无法应用 ID。

如何对 Twitter Bootstrap 弹出框内容中的某些内容应用事件处理程序?


你有两个选择。#1:在弹出框打开后重新绑定它,或者#2使用事件委托进行绑定。这个按钮需要做什么? - Kevin B
很多不同的东西,有些通过js提交表单,有些只是简单地关闭弹出窗口。 - Hailwood
7个回答

36

我遇到了同样的问题,但在我的情况下,$(body).on('click') 方法行不通,因为应用程序有很多点击按钮。

我改用了以下方法。这样,我们可以将代理事件的范围限制在弹出框元素的父元素内。

$('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. 我在我的应用程序中的Backbone.View中使用了这种技术。如果您也在使用Backbone.js,这是在Fiddle中代码的片段...: http://jsfiddle.net/dashk/PA6wY/

编辑 在Bootstrap 2.3中,您可以指定一个目标容器,将弹出框添加到其中。现在,您不必使用.parent()定位器,还可以专门监听容器事件...这可以使侦听器更加具体(想象一下创建只存在于包含弹出框的DIV中的情况)


在2.3版本之前,这是一个很好的答案,我在2.1.1上使用过,效果很不错。 - mccainz

28

这应该就可以了。它将处理在带有.popover类的元素内创建的任何现有和未来的按钮元素:

$('body').on('click', '.popover button', function () {
    // code here
});

2
只有当我希望所有按钮执行相同的操作时,这才有效。 - Hailwood
对不起,我刚注意到你原帖中的那一点。你不能为每个弹出窗口指定一个特定的类吗? - manishie
@Hailwood 为什么不使用id而是使用类呢?动态生成的id应该可以胜任! - lomelisan

11

对我而言非常简单的解决方案是:

// 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');
});
为什么这个方法有效:
基本上,当弹出框没有打开时,它的内容没有监听器。
当弹出框显示时,Bootstrap会触发shown.bs.popover事件。我们可以使用jQuery的on方法将事件处理程序附加到$(a.foo)上。因此,当弹出窗口被显示时,将调用处理程序(回调)函数。在这个回调中,我们可以为弹出框的内容附加事件处理程序,例如:当用户点击弹出框内的按钮时会发生什么。
弹出框关闭后,最好删除所有已附加到弹出框内容的处理程序。通过使用hidden.bs.popover处理程序,并使用jQuery的.off方法来移除处理程序。这可以防止在再次打开弹出框时多次调用弹出框内的事件处理程序...

10

仅对DashK的好答案进行轻微更新:自jQuery 1.7起,.delegate()已被.on()取代(请参见 此处)。

$('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!');
});

查看 jsfiddle 这里: http://jsfiddle.net/smingers/nCKxs/2/

我也遇到了一些关于将 .on() 方法链接到 $('a.foo') 的问题;如果你有这样的问题,请尝试将它添加到 document、body 或 html,例如:

$('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!');
});

在类似的思路上,基于这个答案,以下代码对我也起作用:$('a.foo').popover({ html: true, title: '你好', placement: 'bottom', content: '<button id="close-me">关闭我!</button>' }).parents('body').on('click','button#close-me',function(){ console.log('弹出框按钮被点击了!'); }); - tofirius

1

如果在弹出框的内容中添加更复杂的结构,例如外部组件,则可能会遇到问题。对于这种情况,以下方法应该可以解决。

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
});

1
$('.btn-popover').parent().delegate('button#close-me','click', function(){
  alert('Hello');
});

如果在静态HTML中设置了数据属性,则上述方法可以正常工作。谢谢 :)

0

试一下这个

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,
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接