I have a wall posting system on a social network that I am currently building which uses jQuery and Ajax to post the message to the wall and php saves it to the DB. After the post appears on the wall there are "comment" and "like" links. I am trying to bring down a comment box when the "comment" link is clicked, however I can't seem to access the element with javascript.
Here is the code to display the wall post:
var wall_post = '<li><div class="user_activity_feed_item_user_pic"><img src="images/temp/prof_pic_temp.jpg" class="avatar"></div><div class="user_activity_feed_item_title">Tyler Bailey</div> <div class="user_activity_feed_item_content"><p class="activity_feed_text">' + textarea_content + '</p> ' + image_html + '<div class="data"><p class="name">' + sitetitle + '</p><p class="caption">' + siteurl + '</p><p class="description">' + sitedesc + '</p></div><div class="user_activity_feed_item_comment_bar"><ul> <li class="activity_feed_timestamp">July 16, 2012 2:08pm</li> <li><a id="comment" href="#">Comment</a></li><li><a id="like" href="#like_view">Like</a></li></ul></div></div></li>';
and here is the code I was trying to use to access the <a id="comment" href="#"> with:
//initiate comment box for status feeds
$(document).ready(function(){
$('#comment_wrapper').hide();
$('a#comment').click(function(){
$('#comment_wrapper').show();
});
});
Any ideas or tips on how I can get this working would be greatly appreciated!
Simply use event delegation, via on() for example:
var listEl = $('ul'); // parent of the newly added li element
listEl.on('click', 'a', function(e){
e.preventDefault();
// do something in response to a click on a link from within
// the newly-added content.
});
JS Fiddle demo.
The important thing to remember is that the element to which you bind, or assign or delegate, the on() method must be present in the DOM at the time of the binding/assignation. So work with the closest parent element of the newly-added elements that exists in the document on DOMReady or onLoad.
You can use on (falling back on delegate if you are using an older version of jQuery) to listen to all click events on a like or comment button:
var comment_wrapper = $("#comment_wrapper");
comment_wrapper.hide();
$(document).on("click", ".comment", function() {
comment_wrapper.show();
});
Don't use live unless you are using a much older version of jQuery that doesn't supply you with on or delegate. It is, if I remember correctly, the least efficient of the event listeners (aside from the bind method) for listening for an event coming from multiple elements.
Also, don't use an ID if there is going to be more than one element on the page with the ID - the ID needs to be unique across the document.
Since the links is produced dynamically use live()
$('a#comment').live("click", function(event){
//your
//actions here
});
Related
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?
I have an anchor tag which created dynamically and this anchor tag has an onclick event like this:
$('#'+educationHistoryId).append("<span>"+degreeTitle+"</span>" + "<a href='javascript:void(0)' onclick='deleteEducationLevel(" + educationHistoryId + ");'>Delete</a>");
when I click on this anchor I got js error saying:
TypeError: 'click' called on an object that does not implement interface HTMLElement.
I suspect some character escaping issue but unable to resolve.
Added
generated html:
<div id="ff8081814734be020147357beda5002b"><span>A Level</span><a onclick="deleteEducationLevel(ff8081814734be020147357beda5002b);" href="#">Delete</a></div>
Try replacing that line with the following, so that the event is bound like this:
var $link = $("<a href='javascript:void(0)'>Delete</a>");
$link.on("click", function() {
deleteEducationLevel(educationHistoryId);
});
$('#'+educationHistoryId).append("<span>"+degreeTitle+"</span>").append($link);
In my (very reduced) test, this seems to work: http://jsfiddle.net/E7LRt/
Is there an actual need to do this with just one line?
I'd suggest the following solution:
var $anchor = $(document.createElement("a")).attr("href","javascript:").text("Delete").on("click",function() {
alert("clicked!");
alert("educationHistoryId: " + educationHistoryId);
});
$("body").append("<span>" + degreeTitle + "</span> ",$anchor);
This works great: Fiddle
I always try to prevent using inline eventhandlers. It's bad practise in my opinion.
Give the span a class and use event delegation.
You can then bind the click event to a existing parent(I am assuming element with id= "#"+educationHistoryId is existing when the event handler attachment takes place) and then delegate the event to the newly added link.
$("#"+educationHistoryId).on("click", <class>, function(){
deleteEducationLevel(educationHistoryId);
});
I have a comment system where a user submits a comment, the comment is processed, then the HTML for the comment is returned. jquery then adds that retrieved HTML to the comment system. that whole system works, but the comment buttons that requir javascript do not work unless I refresh the page. How do make my javascript work on elements added through load, prepend, or append?
Not sure if my question is clear, but here's the javascript I have:
$(function () {
$(".replyform").submit( function (event) {
event.preventDefault();
id = $(this).attr("id").split('_')[1];
text = $('textarea#text_'+id).val();
$.post( "/api/add/comment/", {_csrf: _csrf, id: id, text: text, a: a},
function (data) {
$('#commentreplies_'+id).prepend(data);
$('#replyform_' + id).hide();
});
});
});
I then have elements such as "reply" for each comment that have functions in an external javascript that do not work unless I refresh the page. Hopefully that made sense.
Use jQuery live() (it is deprecated, see on()) function
jQuery has a live method to allow elements that are added on the page after loading to be able to have events already bound by jQuery. You can bind your events using live method as described here.
A second solution, and probably a more efficient one, would be using delegate method to handle events by existing containers and delegating them to the elements inside that container. You can read more about delegate here.
An example solution using live method is as follows assuming you have buttons with class 'reply' in your response data:
$(".reply").live('click', function(event) {
event.preventDefault();
id = $(this).attr("id").split('_')[1];
text = $('textarea#text_'+id).val();
// post won't work since url is missing, but that code remains the same.
// Assuming you get a response like this
// <div><input type="textarea" id="text2" /><input type="submit" id="reply_2" value="submitReply" class="reply" /></div>
// And if you append this to your document
var data = $('<div></div>').html('<input type="textarea" id="text2" /><input type="submit" id="reply_2" value="submitReply" class="reply" />');
$('#commentreplies_'+id).prepend();
$('#reply_' + id).hide();
});
There are few different approaches to this
1) Explicitly init the button inside returned HTML on AJAX success
2) Setup global handler for your button type using jQuery live() function (replaced by on() in 1.7)
3) define button handler right in the markup
Which one do you pick is really up to your specific task.
Capturing all links.
$("a").live("click", function() {
alert($(this).attr("class"));
});
jquery.truncate.js adds in this.
obj.html(str1 + "<div class='truncate-ellipsis' style='display: inline;'>" + options.ellipsisText +
"</div><div class='truncate-more' style='display: none;'>" + str2 + "</div>" +
"<div class='clear'></div>" +
"<a href='#' class='truncate-more-link'>" + options.moreText + "</a>"
);
But when i click the "showmore" on a truncate object (which is a description that exceeds some designated amount of characters), the click does not get captured! Any thoughts?
The content is added in through an ajax call to the server to get a bunch of peoples comments, the comments that run off into way to much get truncated! thanks
Use .attr('className') - the class attribute is called className in JavaScript since class is a reserved (yet unused) keyword. (jQuery automatically converts class to className)
And since empty alerts won't show up that's most likely the reason why you think your handlers are not firing. Actually, that's one of the reasons why console.log() is much better for debugging than alert() even though I have to admin I often prefer alert() due to it simply showing up without me having to open Firebug.
Another reason for your code not working could be a click() handler somewhere up the DOM tree which calls e.stopPropagation() and thus prevents the event from bubbling to the top where the live event's handler is listening.
I'm trying to make a notification area that will show alerts.
return this.each(function() {
jQuery('<div class="' + o['className'] + '">' + o.msg + ' +
'X' + '</div>')
.appendTo(this);
});
This just takes a message pulled from the database, and shows it to the user. If the user clicks the X then it will call dismiss() which will mark it as being read in the database.
The thing is, if the message itself contains a link to another page or external site, I also want to call dismiss() before the user leaves the page. Is there anyway to alter this javascript to take all a elements (the X and any links that would appear in the message) and change the onclick to call the function?
You can rearrange your code a bit and use .delegate(), like this:
return this.each(function() {
var id = o["id"];
jQuery('<div />', { 'class': o['className'], html: o.msg })
.append('X')
.delegate('a','click', function() { $(this).parent().remove(); dismiss(id); })
.appendTo(this);
});
This uses the new jQuery(html,props) added in jQuery 1.4 to make the creation a bit cleaner (and faster! document fragment caching!). What it's doing is instead of attaching an onclick to the X, it's listening for a click from any <a> in the div and when it bubbles, it executes the same code as it used to only on the X anchor.
The code example is a bit vague, where does this o come from? Is it global or something div-specific?
At any way, you may find jQuery.live() useful for this. Once initialized, it will be applied on all future new elements matching the selector. You only need to have some parent element which is going to contain all of those divs with the messages and the links.
$('#someDivId a').live('click', function() {
// Do your thing here as you did in `onclick` attribute.
};
Just execute it once during onload.