Best way to assign Jquery events to Dynamic buttons - javascript

I am generating twitter bootstrap modals dynamically based on the user action (Long Story). Lets say some times user can see 100 modals on his screen. In each and every modal I have 5 dynamic buttons, each have it own purpose and did same in all modals, and have different id's.
I am attaching onClick events to those buttons by using jquery when ever there is a new twitter modal opens up by using the button id as follows
$(document).on("click","#btn"+btnNumber, function(){
//Code Goes Gere
});
So If I open 100 modals, each have 5 buttons, Is it good idea to assigning click events for 500 times ?
or Is it good Idea to assign click events by using it's name attribute for 1 time as follows
$(document).ready(function(){
$(document).on("click","btnNameAttr", function(){
//Code Goes Gere
});
});

The jQuery on() can help you in this. First you need to detach appending DATA to your element ID like btn+btnNumber. You can add your custom information in any data-x attribute like data-custom-info and use the jQuery attr('data-custom-info') syntax to retrieve the information. The event handlers registered with on() method is also available for future elements(elements created after script execution). Like below.
When creating new button, add render it as..
<input .... class="btnWithData" data-custom-info="1" ... />
<input .... class="btnWithData" data-custom-info="2" ... />
and your event handler goes like..
$(document).ready(function(){
$('body').on('click','.btnWithData',function(){
//DO WHATEVER
var buttonData=$(this).attr('data-custom-info');
//DO WHATEVER
});
});

You should assign delegated event listeners using jQuery.on() method as #Ananthan-Unni suggests, but in the form:
$.on('click', 'button', listener)
In this case you do not need to assign unique ids or attributes. You can use tag name or class name as a selector (2nd argument).
Have a look here: https://api.jquery.com/on/ and read on delegated events.

Best is don't use closures they require memory. Rely on good old data tags, instead:
$(document).ready(function () {
$("#wrapper").on("click", "btnNameAttr", function () {
var n;
n = $(this).data("number");
// code goes here
});
});
To differentiate the actually clicked element inside #wrapper you use data-number attributes like this:
<div id="wrapper">
<img data-number="000" />
<img data-number="001" />
<img data-number="002" />
<img data-number="003" />
</div>
This code will perform much better and you can still have all functionality you want by using wrapping <div> elements and data-number="" attributes. And you don't interfere with class or id attributes you might already have on those elements.
You can even add the command to the tag:
<img data-number="000" data-command="edit" />
<img data-number="000" data-command="show" />
<img data-number="000" data-command="delete" />
And switch on it:
switch ($(this).data("command"))
{
case "edit":
// edit element with number n here
break;
}

Related

Get sibling div id generated by PHP

I have HTML code for kind of blog page. Below - code of 1 post and its height cuts by CSS. It will be many posts on blog page. I want to see all content of particular page by clicking "Read More" button.
Div with blog content has dynamic id which gets from database by PHP.
How can I change height of div with class "blog_article" by clicking "Read More" button?
I thought of using JS/Jquery but cannot get id of "blog_article" div.
Or maybe there is some better way to do this?
<div class="blog_article_wrapper">
<div class="blog_article" id="<?php echo $id; ?>">
<!--Some content-->
</div>
<div class="blog_article_read_more">
<button onclick="blogReadMore()">Read More</button>
</div>
</div>
but cannot get id of "blog_article" div
Why can't you?:
<button onclick="blogReadMore(<?php echo $id; ?>)">Read More</button>
Or, if it's a string:
<button onclick="blogReadMore('<?php echo $id; ?>')">Read More</button>
Then blogReadMore() has a reference to the id:
function blogReadMore(id) {
// use the id to identify the element and modify it however you want
}
Conversely, since you tagged jQuery, you can traverse the DOM from the button click to determine the element without needing any id at all. Something like this:
$('.blog_article_read_more button').click(function () {
var article = $(this).closest('.blog_article_wrapper').find('.blog_article');
// do whatever you like with the article
});
There's a more straight forward way than Azim's answer, but based on the same ideas:
I would still use the read_more class, although not actually needed. I will assume such a class applied to the button.
$('.read_more').click(function(){
var blog_article = $(this).parent().parent().find('.blog_article');
blog_article.css('height', '100px'); //change height here
});
In this case I use .parent() method in order to get the parent object from the clicked item, rather than relying on .closest(). Two calls to .parent() are needed because the <button> resides inside a <div> and we need the parent of that div before we can drill down.
Alternatively:
$('.read_more').click(function(){
var blog_article = $(this).parent().prev();
blog_article.css('height', '100px'); //change height here
});
Because the button's parent <div> is the direct sibling of the one we're interested in. No selectors needed at all!
You have the id right there, you can generate it just fine with blogReadMore('<?php echo $id; ?>'). But you don't need the id, your button lives inside the thing you need expanded so you can look it up that way, too.
You're using fairly ancient JS event handling techniques so this won't be as clean as modern code should be (which doesn't use onclick and other things, but adds the event listening after the DOM has been set up), but you can just pass onclick="blogReadMore(this)" so that your blogReadMore function knows the element that triggered it. Then you just go through the sequence of element.parentNode until you find the element with element.classList.contains('blog_article')===true (both of those have equivalent jQuery calls)
Sort of an answer, but the real one would be "this is not a very good way to generate your code. Generate the HTML and then attach the JS event handling afterwards".
Use a class for read more button, say read_more like <button class="read_more">Read More</button>. And use following jquery.
$('.read_more').click(function(){
var blog_article = $(this).closest('.blog_article_wrapper').find('.blog_article');
blog_article.height(100); //change height here
});

trigger click an element with a specific class and attribute

I have few link elements related to a certain class and assigned row attributes to it and I'm trying to trigger click event based on the attribute value.
<a class="manage_edit_nb" nb_id="1"></a> | <a class="manage_del_nb" nb_id="1"></a>
<a class="manage_edit_nb" nb_id="2"></a> | <a class="manage_del_nb" nb_id="2"></a>
<a class="manage_edit_nb" nb_id="3"></a> | <a class="manage_del_nb" nb_id="3"></a>...
Is it possible to trigger click or any event for a certain attribute value for a certain class?
If I try something similar to
$('a[nb_id = "1"]').trigger('click');
it triggers click event for all elements irrespective of class but I failed to figure out how to put class reference in there!
First, the nb_id is not a valid attribute, use data-id instead. data-* attributes are allowed, and I personally like them. And, they can be accessed using $.attr('data-id') method, and their value can bee updated using $.attr('data-id', 'new value'). Going back to the question, try using below selector
$('.manage_del_nb[data-id="1"]').get(0).click();
OR
$('.manage_edit_nb[data-id="1"]').get(0).click();
Why .get(0)? Assuming that the element has been bound with .click(callback()) or .on('click'), the .trigger('click') will not do anything, so I am using .get(0) to get the DOM object which has that method to simulate the click event. Regardless of being said, you can use trigger('click') the way you're already using
This should work fine.
$('a.manage_edit_nb[nb_id="1"]').trigger('click');
here it is working:
https://jsfiddle.net/link2twenty/g0txnzfw/
The thing that you are trying to do by the above code is triggering a click event on both '.manage_edit_nb' and '.manage_del_nb' selector and hence the event is occuring on both. Try to be little more specific by giving the class name like
$('a.manage_edit_nb[nb_id = "1"]').trigger('click');
I think this is exactly what you need : First of all, change all nb_id to data-nb_id. and use the following code, needs jquery.
$(document).ready(function() {
// Handle click event on the class required
$('.manage_edit_nb').click(function(){
// Get nb_id of that particular anchor event of the class
var nb_id= $(this).attr('data-nb_id');
// Switch on nb_id
switch(nb_id){
// Handle your cases separately here
case "1":
alert('Case 1');break;
case "2":
alert('Case 2');break;
case "3":
alert('Case 3');break;
}
});
});

Clicking on image does nothing

I am trying to create a click event for an image using jQuery but I fail every time I try.
First I have a div:
<div id="price-holder"></div>
then I am using jQuery to insert this HTML by using the following:
$("#price-menu li:nth-child(2)").click(function() {
var pregHTML = $("#cakesmash-price").html();
$("#price-holder").html(pregHTML);
});
However, using this HTML doesn't work
<div id="cakesmash-price" style="display:none">
<img id="cake" src="images/order.png" height="32px" onclick="pregbasic(this);">
</div>
I tried to use the attribute onclick for the image and also tried using jQuery's selector with the ID like so
$("#cake").click(function(){
})
but both didn't work.
Can anyone help me?
Thanks
This assumes that the element is actually being added to the page.
I am betting you are adding the click event before you add the element to the page meaning the selector did not find anything so it did not add the event.
Either add the event after you add the element or use event delegation.
$("#price-holder").html(pregHTML);
$("#cake").click(function(){
});
or
$("#price-holder").on("click", "#cake", function () {
});
Your error could be due to your choice of selectors "#price-menu li:nth-child(2)". Try using the JS .children and .eq selectors. Also if your code was added dynamically consider using the .on() event handler rather than the .click().
Just start with the DOM you actually want, without using jQuery to do this:
<div id="price-holder">
<div id="cakesmash-price" style="display:none">
<img id="cake" src="images/order.png" height="32px">
</div>
</div>
Then you can just add you click handler on #cake:
$('#cake').on('click', function (event) {
// your logic goes here
});

Dynamic ID / Dynamic Functions / Jquery Dialogs

I have the following html, dynamically created.
<a class="open"></a>
<div class="dialog"></div>
<a class="open"></a>
<div class="dialog"></div>
<a class="open"></a>
<div class="dialog"></div>
<a class="open"></a>
<div class="dialog"></div>
Using the follwing jquery, I'm assigning ID's to each a aswell as each div
$('a.open').prop('id', function(i){
return '' + (i + 1);
});
$('div.dialog').prop('id', function(i){
return 'dialog' + (i + 1);
});
I'm then using the assigned ID's to trigger a jquery ui Dialog pop-up, however, I'm having to rewrite the function below for x number of times. Is there a way to create the below function so I do not have to rewrite it x number of times. (x being the max. number of times the the divs may appear on page).
$("#1").click(function(){
$("#dialog1").dialog("open");
});
Sounds like an ideal use for data attributes. When you dynamically generate the <a> tags, assign them a data attribute like so:
<a class="open" data-openNumber="1"></a>
(You can also do this via jQuery, of course).
Then all you have to do is write a single click handler:
$('body').on( 'click', '.open', function(){
var num = $(this).data('openNumber');
$('#dialog'+num).dialog( 'open' );
});
Note that I don't attach the handler directly to elements with class open; if I did that, I would have to do it every time the elements were dynamically created. Instead, I attach the handler to the body, and filter it by class open; that way I don't have to keep re-declaring that click handler. If you have a more handy enclosing class, you can use that instead of body, but not knowing your page structure, I didn't know what that element would be, so I just used body.
I made a jsFiddle to demonstrate the concept. I hope it's helpful:
http://jsfiddle.net/Jammerwoch/Z9U67/
What about this?
HTML
<a class"open" data-id="1">open</a>
<div class="dialog" data-id="1"></div>
JS
$(document).on("click", ".open", function(e) {
var id = $(this).data("id");
$(".dialog[data-id="+ id +"]").dialog("open");
});
If you are only using the id attribute to listen for clicks later on. It makes more sense to create a single event listener for the group.
$("a.open").on("click", function(){
$(this).find(".dialog").dialog("open")
});

JQuery click listener for class

I have a class of images in HTML, with IDs img1,img2,...,img9. I want to make links (HTML a tag) with IDs link_img1, link_img2, ..., link_img9 so that whenever I click on a link, the corresponding image appears.
I'm thinking about assigning all the links to the same class, then add a JQuery click listener for that class, and inside the listener, look for the ID of that link, and shows the corresponding image. How do I add a JQuery listener for a class, and how do I get the ID from the element?
You shouldn't use the ids of a tags to define their target.
Better use the href attribute instead:
<img id="img1" ...>
<img id="img2" ...>
Click me
Click me
jQuery("a.image-link").click(function(){
$(this.href).show();
});
This allows you to have two links for the same image.
Try:
$('a.yourClassName').click(function(){
$('img#'+ this.id).show();
});
To add a listener for a class, just select it the jQuery way (i.e. $('elem.class'). Then use attr() to get the id.
Here. As mentioned in some other answers, id is probably not the best way to determine what action you should take. Use another attribute as you see fit
$('a.some-class').click(function() {
switch (this.id) {
case 'one':
// do something
break;
case 'two':
// do something
break;
default:
// do something
break;
}
});
try this
$('a.yourClass').click(function(){
var $linkID= $(this).attr('id');
$('img#'+ $linkID).show();
});

Categories