I want to create a new element and assign this element the same event for onclick, which it has created it.
DEMO
$(function(){
var counter = 0;
$('.sub').click(function(event){
event.stopPropagation();
counter++;
$div = $(this); // makes more sense in the original code
$div.append('<div class="sub" title="subsub">subsub' + counter + '</div>');
//$div.find('.sub').click // <-- ?????
});
});
In my demo I want to create a new subsub for every sub, which was clicked. Than I want to add the same click event to the new subsub element.
Could anyone help me with this?
I've found nothing for this problem. Maybe I don't have the correct keywords for google or SO :/
Just use event Delegation
$(document).on('click', '.sub', function(event){
Your click events seem to be working correctly at this point,because you are using append which actually nests the new div inside the div that is clicked. Try using after and the functionality breaks.
$(function(){
var counter = 0;
$(document).on('click', '.sub', function(event){
event.stopPropagation();
counter++;
$div = $(this); // makes more sense in the original code
$div.after('<div class="sub" title="subsub">subsub' + counter + '</div>');
});
});
Check Fiddle
Why not create proper elements instead :
$(function(){
var counter = 0;
$('.sub').on('click', doStuff);
function doStuff(event) {
event.stopPropagation();
counter++;
var $div = $(this),
$sub = $('<div />', {'class':'sub',
title : 'subsub',
text : 'subsub' + counter,
on : {
click : doStuff
}
}
);
$div.append($sub);
}
});
Related
How can I call a click event listener on a dynamically created element rendered in the DOM?
I have some scripts that dynamically create elements in the DOM, one of them being a button/a. I would like that button/a to do something once the user clicks it. Right now nothing happens but if I add a setTimeout on the things to happen upon a click, then it kind of works - only let's me do the something on the first element's click (button/a). However I can't rely on a setTimeout to make this chunk of code work.
Here is more or less what I have without the setTimeout method:
// This triggers the whole process
var mainBtn = document.querySelector('.mainBtn');
mainBtn.addEventListener('click', function(e){
e.preventDefault();
mainFunc();
});
// This creates and renders dynamic content in DOM
function mainFunc(){
var out = document.querySelector('.outputWrapper');
var mainArr = ['something ', 'another ', 'else ', 'last one.'];
var div = document.createElement("div");
var btn = document.createElement("a");
var btnText = document.createTextNode("Click Me");
btn.appendChild(btnText);
btn.className = "clickMeBtn";
for(a of probArr){
div.append(a);
div.append(btn);
}
out.append(div);
}
// This is what should happen on button/a click
var clickedBtn = document.querySelector('.clickMeBtn');
if( clickedBtn != null ){
clickedBtn.addEventListener('click', function(e){
e.preventDefault();
console.log('click');
});
}
Here's with the setTimeout method:
// This triggers the whole process
var mainBtn = document.querySelector('.mainBtn');
mainBtn.addEventListener('click', function(e){
e.preventDefault();
mainFunc();
});
// This creates and renders dynamic content in DOM
function mainFunc(){
var out = document.querySelector('.outputWrapper');
var mainArr = ['something ', 'another ', 'else ', 'last one.'];
var div = document.createElement("div");
var btn = document.createElement("a");
var btnText = document.createTextNode("Click Me");
btn.appendChild(btnText);
btn.className = "clickMeBtn";
for(a of probArr){
div.append(a);
div.append(btn);
}
out.append(div);
}
// This is what should happen on button/a click
setTimeout(function(){
var clickedBtn = document.querySelector('.clickMeBtn');
if( clickedBtn != null ){
clickedBtn.addEventListener('click', function(e){
e.preventDefault();
console.log('click');
});
}
}, 10000);
Again this kind of works...it let's me click only on the first instance of the clickedBtn variable.
Any suggestions on how to make this idea work?
Thanks a lot!!
document.querySelector('.clickMeBtn'); returns the first found element, or null.
Attach click event handler when you create the anchor element:
var btn = document.createElement("a");
btn.addEventListener('click', function(e){
e.preventDefault();
console.log('click');
});
I am not 100% sure of what is your question. But the problem I can see is that you cannot bind listeners to elements that are not yet created in the DOM.
So I can see 3 options here:
1- You build a wrapper on top of document.createElement() and a wrapper on top of addEventListener to bind the events to the elements after they are created. For example you build a map of event listeners to begin with, with the 'element selector' as Key and function to call as Value. Then you do a lookup of the listener once the element has been created and you bind it to it with addEventListener.
2- You use JQuery on() method like this:
// define the click handler for all buttons
$( document ).on( "click", "button", function() {
alert( "Button Clicked!" )
});
/* ... some time later ... */
// dynamically add another button to the page
$( "html" ).append( "<button>Click Alert!</button>" );
Source: this JQuery script is from [here][1]
(EDIT) 3- you just bind it after creation, as suggested. Although I thought you wanted to do more advanced stuff, like dynamically add elements asynchronously from the listeners.
I have an ordered list in HTML:
<ol id ="list">
</ol>
which gets added to using JQuery/javascript:
$(function (){
$("#click-me").click(function (e){
e.preventDefault();
i++;
var list = $("#list");
var name = $("#colleague-select option:selected").text();
var remove = "<button type='button' class='remove-me'> X </button>";
var entry = "<li>" + name + remove+ "</li>";
entry.id = "entryid" + i;
list.append(entry);
return false;
});
});
What I'm trying to do is to allow a user to remove an entry in the list by clicking its corresponding button "X". This is the code I've come up with, but it's not working:
$(function (){
$(".remove-me").click(function(e){
var list = $("#list");
var entry = e.parent(); //find parent entry of clicked "X" button
list.remove(entry); //remove entry from list
});
});
Any help guys? I am fairly new to JQuery so an explanation of your answer code would be much appreciated. Thanks.
You need to use event delegation for binding events to dynamically added elements.
$(document).on('click', ".remove-me", function(e){
var entry = $(this).parent();
entry.remove(); //remove entry from list
});
just remove the parent element
$(function (){
$(document).on("click", ".remove-me", function(e){
$(this).parent().remove(); //find parent entry of clicked "X" button
});
});
A foolproof way is add the event to the button
<button type='button' onclick='removeMe(this);' class='remove-me'> X </button>
and on js
function removeMe(e)
{
$(e).parent().remove();
}
I dynamically add some text fields to my page with this line of code:
var textboxCount = 0;
$('#addFields').on('click', function(){
var TextField = document.createElement("input");
TextField.setAttribute("type", "text");
TextField.setAttribute("value", textboxCount);
TextField.setAttribute("name", "textbox");
TextField.setAttribute("class", "foo");
TextField.setAttribute("id", "textbox" + textboxCount);
TextField.setAttribute('onkeyup','doSomething('+textboxCount+');'); // for FF
TextField.onkeyup = function() {doSomething(textboxCount);}; // for IE
jQuery('#TextfieldList').append(eleText);
textboxCount += 1; //Increment the count
});
Now I need the unique ID of the field in this function:
function doSomething(id){
alert(id);
}
But when I call the function, I keep getting the same ID with every added field. The value in the textfield is correct though.
Extremely common problem. Change the keyup handler:
TextField.onkeyup = function(textboxCount) {
return function() {
doSomething(textboxCount);}; // for IE
};
}(textboxCount);
(Get rid of the "For FF" line; it's not necessary at all.)
If you don't introduce a new lexical scope somehow, then all of your event handlers will be referring to the exact same "textboxCount" variable. By doing something like what I've shown above (and there are variations), you ensure that each event handler has its own private copy of the counter as it stood at the time the handler was created.
Since you want to get the id of an element in its own event handler you can bypass the whole closure issue by just referencing this.id, where this is the element and id is its id property
TextField.onkeyup = function() {doSomething(this.id);};
You could just use the jQuery library you have in play:
$('#addFields').on('click', function () {
var thisId = $('.foo').length + 1;
var TextField = '<input type="text" name="textbox" class="foo" value="' + thisId + '" id="textbox' + thisId + '">';
jQuery(TextField).appendTo('#TextfieldList');
});
$('#TextfieldList').on('keyup', '.foo', function () {
doSomething($(this).attr('id'));
// or
doSomething(this.id);
});
function doSomething(id){
alert(id);
}
Sample jsFiddle: http://jsfiddle.net/mHT7Z/
See the code's comment:
$.each($('input[type="radio"]'), function(){
var input = $(this);
var container = $('<div class="radio"></div>');
var mark = $('<span />');
input.wrap(container).after(mark);
container.click(function(){
alert('test'); // Not triggered.
});
});
The html is:
<input type="radio" value="female" name="gender" />
Anyone know why the alert is not triggered when clicked, and yes it is visible in CSS. When I use :
console.log(container);
It does give me the HTML it is containing.
Thanks
$('body').on('click', 'div.radio', function() {
});
Full Code
$('body').on('click', 'div.radio', function() {
alert('test');
});
$.each($('input[type="radio"]'), function(){
var input = $(this);
var container = $('<div class="radio"></div>');
var mark = $('<span />');
input.wrap(container).after(mark);
});
NOTE
Instead of body, you should use a static-element that is the container of container.
Why you need this
You need delegate event handler, as your element added to DOM dynamically that means. after page load.
after some tested it seems to me that the "wrap" clone the object you pass it as argument, or reference to the object is lost but I'm not so sure.
a first solution is to assign the event "onclick" before moving the object in the "wrap".
$.each($('input[type="radio"]'), function(){
var input = $(this);
var container = $('<div class="radio"></div>');
var mark = $('<span />');
$(container).click(function(){
alert('test'); // triggered now.
});
input.wrap(container).after(mark);
});
a simplified version :
$.each($('input[type="radio"]'), function(){
var wrapper = $('<div class="radio"></div>').click(function(){
alert('test'); // triggered now.
});
$(this).wrap(wrapper).after($('<span />'));
});
dont forget to decalare this function in the onload function
$(function(){
// your code here ....
});
I was also affected by this and found that on is available only with jquery 1.7 and above.
I am on jquery 1.4.1 and on is not available with version. Upgrading jquery was something I wanted to avoid.
Thankfully delegate was there and it solved the problem.
I'm trying to add a div to a row of content with the click of a button. My code works for the first row but not for any other row. Please help. This is the function for the button:
$(".addMMbtn").each(function() {
$(this).bind("click",
function() {
var thisRow = $(this).closest(".txtContentRow");
var thisTxt = thisRow.find(".txtContent");
var cellStr = '<div class = "mmCell prep"></div>';
$(cellStr).appendTo(thisTxt);
}
);
});
You can see a fiddle of the problem here: http://jsfiddle.net/z7uuJ/
$(".addMMbtn") will only find the elements present on the page and your code will only attach click event handler on them. Since you are adding the elements dynamically you should either use delegate or on (if you are using jQuery 1.7+) for click event to work on them too. Try this
Using delegate
$('#default').delegate('.addMMbtn', 'click', function() {
$('<div class = "mmCell prep"></div>')
.appendTo($(this).closest(".txtContentRow").find(".txtContent"));
});
Using on
$('#default').on('click', '.addMMbtn', function() {
$('<div class = "mmCell prep"></div>')
.appendTo($(this).closest(".txtContentRow").find(".txtContent"));
});
Demo
Instead of assigning click event directly on the button you need to use on():
$(document).on("click", ".addMMbtn",
function() {
var thisRow = $(this).closest(".txtContentRow");
var thisTxt = thisRow.find(".txtContent");
var cellStr = '<div class = "mmCell prep"></div>';
$(cellStr).appendTo(thisTxt);
}
);
In this case event handler will be subscribed to all newly added elements.
Code: http://jsfiddle.net/z7uuJ/5/
You don't need to loop through the elements to bind the handler:
$(".addMMbtn").live('click', function() {
var thisRow = $(this).closest(".txtContentRow");
var thisTxt = thisRow.find(".txtContent");
var cellStr = '<div class = "mmCell prep"></div>';
$(cellStr).appendTo(thisTxt);
});