Attach event handler to button in twitter bootstrap popover - javascript

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?

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.)

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

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...

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

$('.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 :)

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

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

Related

Click event on dynamic elements not working

In framework7, how to add click event on dynamic elements?
If I add my element first on my view, the click event works fine like below:
<div class="test">Click Me</div>
$$('.test').on('click', function () {
myApp.alert("Gotcha!");
});
But if I have dynamic elements, especially elements dynamically added to virtual-list, I cannot make the click event to work. What is the right way to do this?
I even tried inline function, ex: <div class="test" onclick="myFunction();">Click Me</div>, still this won't work.
You can use:
// Live/delegated event handler
$$(document).on('click', 'a', function (e) {
console.log('link clicked');
});
For your case:
$$(document).on('click', '.test', function(e){
console.log('Some code...');
});
Here is docs. Scroll until events section.
Use this for dinamically added elements:
$$(document).on('click', '.test', function () {
myApp.alert("Gotcha!");
});
All answers are good to go with. But if you are using this class 'test' for other elements of the page, you will end up firing some extra click event(when you click on any other element of same class). So if you wanna prevent that, you should add listener to that particular element.
if you're adding an element of class test to an existing element of id testId, then use
$('#testId').on('click', '.test', function(this){
}
In the function where you dynamically add the new elements you have to assign an event handler for them.
Lets say you have a function something like this
function addNewLines(){
//add the new lines here
// you have to run this again
$$('.test').on('click', function () {
myApp.alert("Gotcha!");
});
}

Create Simple Listener for Link Clicks

I have a fiddle here.
Still trying to figure out Ext JS. How do I fire a click event when a link is clicked? Should be the simplest thing in the world right? The alert should appear when clicking the a obviously but not the span. Also, I want to move that chunk of code that attaches the listener into a ViewController if possible.
var container = Ext.create('Ext.Container', {
renderTo: Ext.getBody(),
html: '<div><a class="test">test....</a><br><br><br><span>some text</span></div>',
listeners: {
click: function(){
Ext.Msg.alert('I have been clicked!')
}
}
});
container.down('a.test').on('click', function(){
this.fireEvent('click', container);
}, container);
I was trying to follow the instructions here in the "Listening for DOM Events" section.
Also, once my handler function returns, I don't want any other handlers to potentially fire.. so I guess the equivalent of jQuery preventDefault.
You can simply use the listeners too, like:
listeners: {
click: {
element: 'el',
delegate: 'a',
fn: function() {
Ext.Msg.alert('I have been clicked!')
}
}
}
A working example based on yours: https://fiddle.sencha.com/#fiddle/v72
(The delegate can be any selector)
You were almost there.
You need to use getEl() in your listener to retrieve the actual DOM element, in order attach the listener to it.
container.getEl().down('a.test').on('click', function(){
this.fireEvent('click', container);
}, container);

jquery click not working on dynamically added hrefs in IE11

Hello I have some links in my HTML code. I want to change the href property of each link on hover and then on clicking this link I want to open it up in a new tab. The code is as follows:
$('.identifierClass').hover(function(e) {
if(condition) // is true
{
$(element).attr("href", "url/goes/here").off().click(function(e) {
$(element).attr("target", "_blank");
});
}
});
Everything is working properly in Chrome/Firefox, however, on clicking the link in IE 11 it simply hangs and click wont work.
Any help is appreciated.
You need to bind to a static or preexisting element that the dynamic elements will be created inside of:
$(document).on('mouseenter','.identifierClass',function(e) {
if(condition) // is true
{
$(element).attr("href", "url/goes/here").attr("target", "_blank");
}
});
Edit: here is a fiddle of it and I also had to use 'mouseenter' instead of 'hover' when using the string name for the event. jquery .hover() documentation
In the fiddle i show you two divs being added dynamically:
$('#place').html('<div class="identifierClass">hover1</div><div class="identifierClass2">hover2</div>');
Above that, I set my event handlers, for hover1 div, I set the event on the document using a specified selector:
$(document).on('mouseenter','.identifierClass',function(e) {
alert('hi');
});
You can see this works when you hover of 'hover1' text on the right and, conversely, you can see hover2 doesn't work using this binding:
$('.identifierClass2').hover(function(e) {
alert('hi2');
});
here is a link to the jquery documentation on event delegation.
Edit2: I updated the fiddle to address the 'href' manipulation. It appears that you just want to change some attributes on the hover portion:
I modified the 'mouseenter' binding to look like this:
$(document).on('mouseenter','.identifierClass',function(e) {
alert('hi'); $('#someLink').attr('href','http://www.bing.com').attr('target','_blank');
});
I don't think you need the 'off' or the 'click', but that is based off of some assumptions, so please feel free to comment and I can update accordingly. This, though, will change the href when the mouseenters the dynamic element and change the target attribute as well.

Can't Add Event Handler Into Button With ID

I've got a jQuery plugin installed on a website I'm working on. The plugin in question adds a modal dialogue to the website when a certain image is clicked. I wanted to add a second button to this modal, to close the window in addition to the close button that already does so, and I managed to do this by creating a div for the button in the HTML. Note that the content for the modal is set in the plugin's content variable, so looks like this:
content: '<p>Want to get in touch? Drop us an email at:</p><br/>
<p><input type="text" id="inset" name="inset"
value="shoesfromlastnight#gmail.com"
onClick="javascript:this.focus();this.select();"
readonly="readonly" size="30"/></p> <br/>
<span id="appendto"><p>We look forward to hearing from you!</p></span>
<div type="button" id="crmbutton">Okay</div>'
...where #crmbutton is the div I want to use as a button. For some reason, though, I'm having trouble with setting the event handler to the button created there in order to make it close the modal. It sounds simple enough, but for some reason won't work when I do:
$("#crmbutton").click(function() {
this.close();
});
Although I couldn't find any documentation on it, the close() method I'm using here is the very same that is used by the plugin's own X button to close the modal. For what it's worth, here's that button's code, first to create the close button and then, using the .on method, to close the modal on click:
this.closeButton = jQuery('<div/>', {'class': 'jBox-closeButton jBox-noDrag'}).on('touchend click', function(ev) { this.isOpen && this.close({ignoreDelay: true}); }.bind(this));
I also copied everything after the .on method and applied it to my code, but wasn't successful with that either.
I also tried other approaches, like adapting the code above to create the button on the fly, and then appending or prepending it using the append/prepend methods. This worked, but only when appending to the modal's container, which always added the button outside of the container. I had no luck with appending the button after certain elements, like the #appendto - the button just wouldn't be added.
Does anyone know where I could be going wrong here? This is the first time I've worked with jQuery, and it's frustrating me to no end. Thanks!
The problem is because you're not calling the close method in the correct scope. In your eventlistener, 'this' points to the button. But in the code that you looked at, 'this' has been changed to another scope with the .bind() method.
$("#crmbutton").click(function() {
/* 'this' points to the element #crmbutton, which doesn't have a close method */
this.close();
});
The example code, look at the bottom where the .bind() method is used.
this.closeButton = jQuery(
'<div/>',
{
'class': 'jBox-closeButton jBox-noDrag'
}
).on(
'touchend click',
function(ev) {
this.isOpen && this.close({ignoreDelay: true});
}.bind(this) /* The scope is being set to another 'this' */
);
Documentation about the .bind() method

Dynamically added javascript is not working, but static code works fine?

Here is what I'm doing... I have a textbox that users type something in and click an add icon. This fires some jquery code that adds the item they typed into a span within a "content" div. The generated code has a delete icon that appears on hover and when clicked it should make the span disappear. This works if the code is on the page already (before document load) but if it's dynamically created, it breaks the delete on click functionality.
Here is a JSfiddle so you can see it in action: http://jsfiddle.net/WF32y/
What can I do to fix this? I essentially want to do what happens on here (stackoverflow.com) when you enter tags to a new question.
Use event delegation for dynamically added elements by changing this:
$('a.delete').on('click', function(e) {
Into this:
$(document).on('click', 'a.delete', function(e) {
Fiddle
.on() Direct and delegated events reference
Also, concerning performance, you can attach the handler to a closer ancestor of the dynamically added elements than the document (e.g. a static wrapper element).
You can easily do it with delegate. In your case:
$('#container').delegate('a.delete','click', function(e) {
e.preventDefault();
taskID = $(this).closest('.task')[0].id;
$(this).closest('.task').fadeTo(300, 0, function() {
$(this).animate({
width: 0
}, 200, function() {
$(this).remove();
});
});
});
And by the way FYI:
// jQuery version 1.4.3+
$('#container').delegate('a.delete'...
// jQuery 1.7+
$('#container').on('click', 'a.delete', function(e) {
it is faster and more propery way than:
$(document).on('a.delete'...
or:
$('body').delegate('a.delete'...
or:
$(document).delegate('a.delete'...

Categories