JS delegate unique event (one()) for dynamic declared elements - javascript

I'm working on js-project. Some parts of HTML is generating via JS like this:
html += '<div class="button"><a href="' + url1 + '>' + button_text1 + '</a></div>';
html += '<div class="button"><a href="' + url2 + '>' + button_text2 + '</a></div>';
What I want is create listener to the first click for each of the buttons.
Idea 1: Use $(.button a).live('click', doSomething) because of dynamic declaration. Sadly, there's no way to force trigger only on the first click like that. Also deprecated.
Idea 2: Use $(.button a).one('click', doSomething). Not working because of on() might fail to find selector when DOM is ready, but still rendering ($(document).ready(...)). See details here: https://jqueryhouse.com/jquery-on-method-the-issue-of-dynamically-added-elements/
Idea 3: Use $(body).one('click', '.button a', doSomething), i.e. delegate event as noted source suggests.
But it seems like JS is read it not as "Here is an array of elements; for each element add one('click') event", but as "Add one('click') event for click on any element from an array", because an event is triggered only once no matter what button I have clicked.
I was really trying to find any clues to how manage this situation but got no luck. I will be really grateful for help or another idea how to solve this!

«I want is create listener to the first click for each of the buttons.»
The keyword here is each.
Try that:
$(.button a).each(function(){
$(this).one('click', doSomething); // (!)No prenthesis here... Just the function name.
});
Documentation for the .each() method.
Since you append new elements dynamically... After you appended html to a container, run a similar each loop on them like this:
// Assuming you do this
$(".container_selector").append(html);
// Then run the each loop
$(".container_selector").find(".button a").each(function(){
$(this).one('click', doSomething); // (!)No prenthesis here... Just the function name.
});

You are overthinking things. So use event delegation and some flag that says if it has run or not.
$(document).on('click', '.test', function() {
var elem = $(this) // what was clicked
if (elem.data('clicked')) { // see if we clicked it
return false // if yes, ignore the click
}
elem.data('clicked', true) // mark it was clicked
elem.html((new Date).toLocaleString()) // do something
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="test">1</div>
<div class="test">2</div>
<div class="test">3</div>
<div class="test">4</div>
Or go off a class that has not run and remove it
$(document).on('click', '.test-run', function() {
var elem = $(this) // what was clicked
elem.removeClass('test-run') // remove class so will not be clickable
elem.html((new Date).toLocaleString()) // do something
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="test test-run">1</div>
<div class="test test-run">2</div>
<div class="test test-run">3</div>
<div class="test test-run">4</div>

Related

javascript click event not firing action

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?

Trying to hide() an element with jQuery

I have code that does this:
$('.attachment-medium').each(function(){
$(this).click(function(){
var gallWidth = $('.gallery').width();
$('.gall-output').toggle().css('width', gallWidth);
var url = $(this).attr('src').slice(0,-12) + '.jpg';
$('.gall-output-img').html('<img class="img-responsive" src="' + url + ' "/>');
var imgMeta = $(this).parent().next().html();
$('#gall-output-meta').html(imgMeta);
});
});
This generates a modal overlay and displays an img withing a div with class .gall-output. I've created a small <p class="gall-close">close</p> to hide() the .gall-output but it doesn't seem to be working with this code:
$('.gall-close').click(function() {
$('.gall-output').hide();
});
Is there a way of using this .gall-close to hide or toggle .gall-output?
Thanks for your help.
In case the .gall-close is added later and not in the dom when the page is loaded, you can attach the click-event using event-delegation:
$(document).on("click", ".gall-close", function(){
$('.gall-output').hide();
});
Instead of $(document) any static parent element can work as container element to delegate the event. In case this solves your issue, you can check https://api.jquery.com/on/#on-events-selector-data-handler, section "Direct and delegated events":
"Event handlers are bound only to the currently selected elements; they must exist on the page at the time your code makes the call to .on()."

Onclick event on dynamic created anchor tag

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

Trigger Event on Ajax generated Element

I can't use any Event (eg. onlick) on any ajax generated element. I read about jQuery's ".on" function, but I need to use something like <div id="myId_1234" onlick="doStuff()">.
The Id of the Element is random, so I can't use
`$('.some-parent-class').on('click', '.element', function() {// DO STUFF!});`
I hope someone can help me! Thanks.
You could attach the event handler to your element in the AJAX response before adding it to the DOM by using
$(responseHtml).find('some selector').on('click', handler);
There is most likely one or more attribute selectors that will work for you.
Ex: id begins with selector
$(responseHtml).find('div[id^=myId]').on('click', handler);
If you cannot differentiate which element in the response you need with a css selector you will have to modify the server script generating the HTML with a unique id or class that matches a pattern you can look for.
EDIT
You CAN use a css class to identify each element. use:
$('.myCloseButtonClass').on('click', function(){ $(this).parent.hide(); });
The key here is the this object. It will reference the specific element that was clicked thereby allowing you to close only the chat window that contains the clicked close button.
JSFiddle using AJAX echo
$('.some-parent-class').on('click', 'this put your id input', function() {// DO STUFF!});
proib with this......
You could do something like:
<div class="myBoxes">
<div id="oneBox" onclick="myFunc(this.parentNode);">
<p>Some content..</p>
</div>
</div>
function myFunc(){
// Code goes here
alert('function fired!');
}
I am simulating the Ajax Generated part by dynamically generating a clickable DIV element.
HTML:
<div id="container">
</div>
JS:
$("#container").append(
$('<div>').attr('id', 'randomId').html('New element')
);
$("#randomId").click( function(){
alert('Clicked!!!');
});
EDIT: Same example using class instead of Id:
$("#container").append(
$('<div>').attr('id', 'randomId').addClass('parent-class').html('New element')
);
$(".parent-class").click( function(){
var clickedElementId = $(this).attr("id");
alert('Element with ID ' + elementId + ' Clicked!!!');
});
Working fiddle

Accessing a dynamically created link with Javascript

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

Categories

Resources