javascript click event not firing action - javascript

On page load, I have a search box that, once used, populates a div with multiple images. The javascript from the search uses this function to append all images into the div
function appendSomeItems(url, id, name, style) {
return '<div><div class="md-card md-card-hover"> <div id="getImage" class="gallery_grid_item md-card-content"> <img class ="uk-align-center imageClick"></a> <div class="gallery_grid_image_caption"> <span class="gallery_image_title uk-text-truncate">' + name + '</span> <span>' + style + '</span> </div></div></div></div>';
}
This works perfectly. Now I'm trying to make it so that when I click any one of the images it triggers an action (in this case a console log)
$('.imageClick').click(function handleImage() {
console.log(good);
});
However, it does nothing. No error but no console log.
What am I doing wrong here?

You need to use event-delegation in order to bind an event to dynamically created elements:
This approach uses document as the parent element, however, a good practice is to use the closest parent element.
$(document).on('click', '.imageClick', function handleImage() {
console.log(good);
});

Try with .on() to attach event on dynamically created element. This will allow attaching the event to the elements that are added to the body at a later time:
$('body').on('click', '.imageClick' function handleImage() {
console.log(good);
});

The problem is that you are calling $(".imageClick").click() before you dynamically create the items.
This means that jQuery doesn't actually bind the click listener to the items, since when $(".imageClick").click() is run, the elements don't actually exist yet.
Try this:
$("body").on("click", ".imageClick", function handleImage() {
console.log("good");
});
Also see this post for more information: In jQuery, how to attach events to dynamic html elements?

Related

change div class,id,.. in every click

I trying to run code to change div id,class,... in every click but I don't
know how this my js code :
<div class="up_vote_bt upvote_hide" title="Delete up vote" onclick="upvoteHide()" id="hideupvote"></div>
<script>
$(document).ready(function() {
$("#upvote").click(function() {
document.getElementById("upvote").setAttribute("class","up_vote_bt upvote_hide");
document.getElementById("upvote").setAttribute("title","delete up vote");
document.getElementById("upvote").setAttribute("onclick","hideupvote()");
document.getElementById("upvote").setAttribute("id","hideupvote");
});
});
</script>
<script>
$(document).ready(function() {
$("#hideupvote").click(function() {
document.getElementById("hideupvote").setAttribute("class","up_vote_bt");
document.getElementById("hideupvote").setAttribute("title","up vote");
document.getElementById("hideupvote").setAttribute("onclick","upvote()");
document.getElementById("hideupvote").setAttribute("id","upvote");
});
});
</script>
if you're using jQuery why not do this?
$(document).ready(function(){
$('#upvote').click(function(){
//$(this) for just this element
if($(this).hasClass('upvote_hide')){
$(this).attr('title','Up vote');
upvote();
}else{
$(this).attr('title','Delete up vote');
hideupvote();
}
$(this).toggleClass('upvote_hide')
});
});
toggleClass() will either add or remove upvote_hide if it doesn't exist or exists.
attr() will alter the attribute much like setAttribute()
For my example there is no need to alter the eventHandlers or in your case setting the attribute onClick to the function. I'ts all done in the jQuery event hander function. So your functions that you're passing to the onclick attribute are called within the function.
When you attach an event handler via jQuery using the
$("#upvote").click(function() { ... });
mechanism, jQuery will directly attach the handler to the elements in the query result set. This means that the handler will be there, whatever the ID changes to in the future.
What you can do is to attach a delegated handler to the document like this.
$(document).on("click", "#upvote", function() { ... });
$(document).on("click", "#hideupvote", function() { ... });
See this article for a deeper explanation
Also, setting the onclick attribute is meaningless in this case and you should remove those lines.
However, changin IDs of elements is not a good practice. An ID should mean a unique identifier for a DOM node, which is not expected to change. I would rather toggle classes here.

jQuery .on('click') firing multiple times when used with :not() selector

Good morning,
I have a set of boxes on a page that are presented as a list, and within these boxes there might be some links that can be clicked. I want the links within the boxes to work as normal (i.e. bubble up and either perform the default action or then be handled by event handlers further up the DOM), but if the box is clicked anywhere else then it should be caught by a particular event handler attached to the "list" containing all the boxes.
Simple html representation
<div class="boxlist">
<div class="box" data-boxid="1">
Some text, and possibly a link and another link, and perhaps even a third link.
</div>
<div class="box" data-boxid="2">
Some more text, this time without a link.
</div>
</div>
The javascript that I thought should work.
$(function () {
$('.boxlist').on('click', '.box :not(a)', function (e) {
var boxid= $(this).closest('.box').data('boxid');
console.log('open: ' + boxid);
});
});
My expectation was that the above javascript should handle all clicks that did not originate from tags. However, for some reason when the box is clicked (either the box itself, or an tag, doesn't matter), it fires this event X times, where X is the total number of tags within the list of boxes.
So I have two questions:
1. What am I doing wrong with the :not() selector.
2. Is there a better way to handle this scenario?
Thank you for helping!
linkUsing jQuery :not selector actually is very slow ex:http://jsperf.com/not-vs-notdasdsad/4 and it's way better to just use event delegation. So in this case you want to keep track of every click on the .boxlist but check the node type to see if its an anchor or not. This is an example.
$(function () {
$('.boxlist').on('click', function(ev){
if(ev.target.tagName != "A"){
// handle box click code
console.log('box click');
return false;
}
// Otherwise allow event to bubble through.
});
});
and here is a jsfiddle example
http://jsfiddle.net/drXmA/
Also their are a few reasons your code doesn't work
.box :not(a)
should be
.box:not(a)
and the reason this also does not work is because .box is not an anchor tag it has children elements that are anchor tags it will never find an anchor tag named .box if their is one the callback would not execute. Changing the .box to an anchor tag will make it so the code doesn't execute because .box is an anchor and it is only running when .box:not(a)
I guess you want something like this:
$('.boxlist').on('click', '.box:not(a)', function (e) {
var boxid = $(this).closest('.box').data('boxid');
console.log('open: ' + boxid);
}).on('click', '.box a', function (e) {
e.preventDefault().stopPropagation();
});
DEMO FIDDLE
I think better to stop the default behavior and stop the event bubbling to its parent. .on() chain to the .box items excluding <a> from it and stop the default behavior and event bubble with e.preventDefault().stopPropagation();

Dynamic Items and jQuery Event Binding

I am currently populating a list dynamically based on some web calls. When these calls return I use an HTML template to add another item to the list based on the call response. I also am trying to attach some events to these objects using jQuery, but when I generate the items it seems like only the last item generated has the appropriate events firing.
So here is the code:
The javascript generates the html string and the adds it to the list:
List.innerHTML += html;
The html is generated using moustache.js and renders properly, I set the id in the template before adding it.
The template has this form:
var template = '<li style="width:400px; height:100px" id="{{id}}" ><img src="{{source}}" style="float:left"/>{{title}} <button id="{{id}}button">Delete</button></li>';
Where all the elements are replaced appropriately.
Then I try to attach a click event to the button and a double click event to the entire list object:
$('#' +id +'button').bind('click', function() {
//SOME STUFF GOES HERE
});
$('#' +id +'button').bind('dblclick', function() {
//MORE STUFF GOES HERE
});
Im not sure why the event wouldnt attach to each object, am I missing something?
Thanks!
The DOM might not have been updated on the browser by the time you add the click handlers. You have a couple options:
Use delegated binding (using .on)
Attach the events before adding them to the DOM
Example 1:
$('body').on('click', '#' +id +'button', function () { /* foo */ });
Example 2:
$('#' +id +'button', myHtml).on('click', function () { /* foo */ });
List.append(myHtml);

Show and Hide handlers are applied multiple times on each click

This is my html code:
<span id="username_{{ member.id }}" onclick="showMembershipData('{{ member.id }}');">{{ member.user.username }}</span>
and this is my jQuery code
function showMembershipData(id)
{
$("#memberInfo_"+id).slideDown();
$("#username_"+id).click(function(){
hideMembershipData(id);
});
}
function hideMembershipData(id) {
$("#memberInfo_" + id).slideUp();
$("#username_" + id).click(function() {
showMembershipData(id);
});
}
I want the user name to be clickable and when clicked open the "more information" pane, or close it if it is opened. What happens now is:
username clicked for 1 time: pane opens.
Clicked 2nd time: pane closes. Up to here is fine...
clicked 3rd time pane opens and closes 2 times in a row (i.e. 4 operations: open, close, open, close)
and so on... Why? What am I doing wrong?
You are assigning handler inside each handler, and you only need to assign handler once or even consider using event delegation $.on(event, selector, handler) if you are adding and removing items.
consider code below, and remove handlers from markup:
add class username to elements with id username_xxx
add class memberInfo to elements with id memeberInfo_xxx
add data-id attribute to elements with id username_xxx
So markup going to look like:
<span class="username" data-id"{{ member.id }}">{{ member.user.username }}</span>
And the script:
$('body').on('click', '.username', function(e) {
var id = $(this).data('id')
$('#memberInfo_'+id).toggle()
})
The problem with your code is that even handlers are been attached multiple times. Basically with jQuery if you do something like
$("#element").click(functionName);
$("#element").click(functionName);
$("#element").click(functionName);
Then clicking the element once will fire functionName thrice! You need to refactor your code a bit to make sure that the event handlers are added and removed appropriately. Try this
function showMembershipData(id)
{
$("#memberInfo_"+id).slideDown();
$("#username_"+id).unbind("click").bind("click",(function(){
hideMembershipData(id);
});
}
function hideMembershipData(id) {
$("#memberInfo_" + id).slideUp();
$("#username_" + id).unbind("click").bind("click",(function() {
showMembershipData(id);
});
}
let's change the code a little bit, shall we
<span
id="username_{{ member.id }}"
class="member"
data-memberid="{{ member.id }}">{{ member.user.username }}</span>
on the jQuery side
$(".member").toggle(
function() { // click - show
var id = $(this).attr("data-memberid");
$("#memberInfo_" + id).stop().slideDown();
},
function() { // click again - hide
var id = $(this).attr("data-memberid");
$("#memberInfo_" + id).stop().slideUp();
});
easy :)
You can make life a whole lot easier by using jQuery's slideToggle() method - try the following:
function showMembershipData(id)
{
$("#memberInfo_"+id).slideToggle();
}
This will toggle the #memberInfo + id (whatever the ID is) when the link is clicked. Can I suggest using jQuery's click() function? (needs a class added to the username span):
$("#username_span").click(function()
{
$("#memberInfo_"+id).slideToggle();
});
Don't forget to add it to your $(document).ready() bit or whatever. Once you've done that, you can remove the onClick from the span.
James
Agree with the guys above...you keep registering the events. If all you're doing is opening and closing one:
$('#clickme').click(function() {
$('#book').slideToggle('slow', function() {
// Animation complete.
});
});
http://api.jquery.com/slideToggle/
Problem here is that you add an event handler each time showMembershipData gets called.
You should make sure only one event handler gets assigned.
It is happenign 2 times in a row because each time you call those functions they bind a click function which fires.
try
$("#username_"+id).click(function(){
var $showHideElement =$("#memberInfo_"+id);
if ($showHideElementis(':visible'){
$showHideElement.slideUp();
}else{
$showHideElement.slideDown();
}
})

Issue with selectors & .html() in jquery?

The function associated with the selector stops working when I replace it's contents using .html(). Since I cannot post my original code I've created an example to show what I mean...
Jquery
$(document).ready(function () {
$("#pg_display span").click(function () {
var pageno = $(this).attr("id");
alert(pageno);
var data = "<span id='page1'>1</span><span id='page2'> 2</span><span id='page3'> 3</span>";
$("#pg_display").html(data);
});
});
HTML
<div id="pg_display">
<span id="page1">1</span>
<span id="page2">2</span>
<span id="page3">3</span>
</div>
Is there any way to fix this??...Thanks
Not sure I understand you completely, but if you're asking why .click() functions aren't working on spans that are added later, you'll need to use .live(),
$("#someSelector span").live("click", function(){
# do stuff to spans currently existing
# and those that will exist in the future
});
This will add functionality to any element currently on the page, and any element that is later created. It keeps you have having to re-attach handlers when new elements are created.
You have to re-bind the event after you replace the HTML, because the original DOM element will have disappeared. To allow this, you have to create a named function instead of an anonymous function:
function pgClick() {
var pageno = $(this).attr("id");
alert(pageno);
var data="<span id='page1'>1</span><span id='page2'> 2</span><span id='page3'> 3</span>";
$("#pg_display").html(data);
$("#pg_display span").click(pgClick);
}
$(document).ready(function(){
$("#pg_display span").click(pgClick);
});
That's to be expected, since the DOM elements that had your click handler attached have been replaced with new ones.
The easiest remedy is to use 1.3's new "live" events.
In your situation, you can use 'Event delegation' concept and get it to work.
Event delegation uses the fact that an event generated on a element will keep bubbling up to its parent unless there are no more parents. So instead of binding click event to span, you will find the click event on your #pg_display div.
$(document).ready(
function()
{
$("#pg_display").click(
function(ev)
{
//As we are binding click event to the DIV, we need to find out the
//'target' which was clicked.
var target = $(ev.target);
//If it's not span, don't do anything.
if(!target.is('span'))
return;
alert('page #' + ev.target.id);
var data="<span id='page1'>1</span><span id='page2'>2</span><span id='page3'>3</span>";
$("#pg_display").html(data);
}
);
}
);
Working demo: http://jsbin.com/imuye
Code: http://jsbin.com/imuye/edit
The above code has additional advantage that instead of binding 3 event handlers, it only binds one.
Use the $("#pg_display span").live('click', function....) method instead of .click. Live (available in JQuery 1.3.2) will bind to existing and FUTURE matches whereas the click (as well as .bind) function is only being bound to existing objects and not any new ones. You'll also need (maybe?) to separate the data from the function or you will always add new span tags on each click.
http://docs.jquery.com/Events/live#typefn

Categories

Resources