Writing this jQuery click function in JavaScript - javascript

I am slowly making my way from jQuery to vanilla JS, but I am struggling with wanting to write the following in JavaScript, would I have to setup a 'for' loop for each element? How would I target the child elements an an ID?
Here's what I would want to understand:
$('#id li').click(function(){
$(this).addClass('active');
});
I understand document getElementById to grab the '#id' but how would I achieve getting the child <li> elements? And how would I get the 'onclick' function to work for ANY list element clicked? Would I have to setup a 'for' loop for each element? Any help much appreciated!

Here is a JSFiddle that does what you want:
http://jsfiddle.net/digitalzebra/ZMXGC/10/
(function() {
var wrapper = document.getElementById("id");
var clickFunc = function(event) {
var target = event.originalTarget || event.target;
target.className = "active";
};
wrapper.addEventListener("click",clickFunc);
})();
A little bit of an explanation is in order...
First, I'm using a self executing function to fetch the wrapper div, using getElementById(). This is equivalent to using an id selector in jQuery: $('#id')
Next, I'm attaching a click handler to the element using the function addEventListener() and passing in an event type of click.
This binds the click handler function to the div element, the same as jQuery's click() would do. I'm using something called event bubbling, where a click event on any of the children of the wrapper will call the click handler attached to the wrapper.
Once the user clicks on the element, our function is called. originalTarget or target is the element that the user actually clicked in to, which in this case will always be an li. I'm then setting the class on that element to active.

Here is example for above question
http://jsfiddle.net/G3ADG/2/
(function() {
var id = document.getElementById("id");
var liele = id.getElementsByTagName("li");
for (var i = 0; i < liele.length; i++) {
liele[i].addEventListener("click", function () {
this.className = "active";
})
}
})();
Well I really liked Polaris878 solution as he is not using any loop inside it. In my solution first get HTML node information using document.getElementById this works similarly to $("#id"). than in next step I am fetching all tag type of "li" which are children of "id", than on this li tag array adding event listener to listen click functionality
className is one of attribute that allow to add class on that Node
I have tested above code in mozilla and chrome

This will work (IE >= 10), not want to search classList.add() replacement for IE<10,
var elems = document.querySelectorAll('#id li');
for (var i = 0; i < elems.length; i++) {
var elem=elems[i];
elem.addEventListener("click", function (e) {
this.classList.add('active');
});
}
fiddle

Related

click event with each loop on dynamicly added elements javascript / jquery

my problem is that the $('input[name=isDefault]').length equal 2, but the each runs ony ones.
$(saveProduct).click(function (e) {
$('input[name=isDefault]').each(function (index) {
var that = this;
console.log(index, 'index');
console.log($('input[name=isDefault]').length);
// do something...
})
})
$('input[name=isDefault]') is dynamicly addes obj during another logic.
I know there is a solution like $(upper container).on("event", dynamic obj inside upper container) - but this causes the click event to be almost everywhere, because .on is attaching event on big area container
EDIT:
I made some changes for testing purpose:
var imgs = imgs = $('div[name=fileContainer]');
console.log('before loop', imgs.length); // = 1
for (var i = 0; i < imgs.length; i++) {
console.log('inside loop', imgs.length); // = 1
//do something - imgs is dynamicly added html element by jquery, when I load page there is 1 element with that name
}
,but when I write $('div[name=fileContainer]').length; in console it's equal 2 (of course when I dynamicly added + 1 fileContainer element)
EDIT:
this isn't the answer, but I omitted the need to use the above loop.
Elsewhere in the code, I already have $(something).on("change", dynamiclyAddedElements function() {}) with difrent main purpouse..., but! there I add addintional function where I created javascipt obj with needed data. Then I can use them in above click event.
$(upper container).on("event", dynamic obj inside upper container) - but this causes the click event to be almost everywhere, because .on is attaching event on big area container
thats not right, you can use the second parameter to specify the selector
e.g
$('#upper_container').on('click', '.saveProduct', function(){...})
will add the click handler to (also dynamically added) .saveProduct and not #upper_container as you claim

How to set up a click event on HTML elements( li ) with JavaScript?

I am having some issues with running a click event.
My purpose is just to track click events basically, very simple stuff. For visual changes I was going to check one of my links to change the HTML text. When I run this code at the moment I get an error:
"document.getElementsByTagName(...).addEventListener is not a function"
var links = document
.getElementsByTagName("a")
.addEventListener("click", myFunction);
function myFunction() {
document.querySelector(".contact-link").innerHTML = "clicked!";
}
You need to loop through all the elements and then add the event listener
var list = document.getElementsByTagName("a");
for(let i=0; i<list.length; i++) {
list[i].addEventListener("click", myFunction);
}
function myFunction() {
console.log("clicked");
}
<span class="contact-link">ABC</span>
<span class="contact-link">DEF</span>
<span class="contact-link">GHI</span>
You can't set the event listener to all elements of the collection at once. You need to iterate over it and set the event listener for each one.
Hope it helps you!

click function within another click function is called multiple times

i am in touch with jquery for the first time and ran into this: I am trying to create a dynamic input-form. A click function creates a new list-item with another click function nested into it (to provide a remove function for the clicked item).
When i execute the nested click function it appears to be called the number of instances that have been created of it.
Here is the code (i tried to remove as much as possible, but i am not quite sure where the error is - so i guess i left to much stuff in - sorry).
$("#addIngredient").click(function(e){
e.preventDefault();
var prefix = "form-"
var last = $("#IngredientForm ul li").last().html();
$("#IngredientForm ul").append("<li>"+last+"</li>");
var name = $("#IngredientForm ul li:last input").attr("name");
name = name.replace(prefix,'');
var count = parseInt(name[0]);
count += 1;
$("#IngredientForm ul li:last input").attr("name",prefix+count+"-weight")
$("#IngredientForm ul li:last select").attr("name",prefix+count+"-ingredient")
$("#IngredientForm ul li:last input").attr("id","id_"+prefix+count+"-weight")
$("#IngredientForm ul li:last select").attr("id","id_"+prefix+count+"-ingredient")
$("#id_form-TOTAL_FORMS").val(count+1);
$(".deleteIngredient").click(function(e){
e.preventDefault();
var aktuell = $(this).closest('li');
var formCount;
name = aktuell.children('input').attr("name");
name = name.replace(prefix,'');
counter = name.replace("-weight",'');
formCount = parseInt($("#id_form-TOTAL_FORMS").val());
aktuell.remove();
--formCount;
$("#id_form-TOTAL_FORMS").val(formCount);
for (var i = parseInt(counter); i<formCount; i++){
var newName = "form-"+(i);
$("#id_form-"+(i+1)+"-weight").attr("name",newName+"-weight");
$("#id_form-"+(i+1)+"-ingredient").attr("name",newName+"-ingredient");
}
});
});
This block
$(".deleteIngredient").click(function(e){...
attaches a clickevent to all .deleteIngredient elements, also those created before.
You have to put this block outsite the click event of #addIngredient. You can make the delete event to be attached also to every element added in the future.
$("#addIngredient").click(function(e){
// ...
});
$(document).on("click", ".deleteIngredient", function(e){
// ...
});
As the other answers have noted, the click handler is adding a click handler to every .deleteIngredient element every time you run it, which adds multiple handlers to all the previous elements.
When you add a new item to the list, you don't have to add a click handler to it. You can use delegation to create a handler one time that will apply to dynamically-added elements:
$("#IngredientForm").on("click", ".deleteIngredient", function(e) {
...
});
See Event binding on dynamically created elements? for more information.
Every time that outer "click" event happens, you're adding another "click" handler for the ".deleteIngredient" element(s). The .click function does not remove previously-assigned event handlers.
You can get rid of old handlers with .unbind or, preferably with new versions of jQuery, .off:
$('.deleteIngredient').unbind('click').click(function(event) {
// ...
});
No, the thing is, here I think you probably want to bind to the .deleteIngredient button that you're adding for the new ingredient. The code you've got — based on the reference to $('.deleteIngredient') — will affect all of the elements on the page with that class. My guess here is that you're adding a button or something for each <li>. Thus, what you should probably be doing is finding the button inside the newly-added structure:
$('#IngredientForm ul li:last .deleteIngredient').click(function(event) {
// ...
});
Use this format instead
$("#addIngredient").on('click', function() {
$(this).off();
});

.class selector not working

I'm working in a card game system that the player can select the card by clicking on it and then select the place to put it on. My problem is that when the player click on the target place, nothing happens.
This is my try: http://jsfiddle.net/5qMHz/
And this is my code:
function target() {
$(".target").on("click", function() {
$("#"+x).appendTo(this);
console.log(x);
});
};
What's wrong?
Try binding with document, since you change the class during document ready and there was no element with the class target initially
$(document).on("click",".target", function() {
$("#" + x).appendTo(this);
console.log(x);
}
WORKING FIDDLE
Firstly, your practice of putting function references in to jQuery objects is rather odd. The problem however is that because the .target class is applied after DOM load you need to use a delegate selector. Try this:
var $card
$(".card").on("click", function () {
$card = $(this);
if ($(".myslot").length) {
if ($(".myslot").is(':empty')) {
$(".myslot:empty").addClass("target");
} else {
alert('No empty slots');
}
}
});
$('.field').on('click', ".target", function () {
$card.appendTo(this);
$card = $();
});
Example fiddle
At the moment you are trying to bind the event handler, the elements don't have a class target yet. From the documentation:
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().
(Technically the elements exist, but they are not (yet) addressable by the class target)
You have three options to solve this:
Add the class to your HTML markup.
Bind the handler after you added the class to the elements.
Use event delegation.
The first two don't really fit to your use case, since your are adding the class target in response to an other event and the number of elements with the class target changes over time. This is a good use case for event delegation though:
$('.field').on('click', '.target', function() {
// ...
});

click event firing multiple times in loop

I am firing click event inside the loop.it fires multiple times .
How can i stop firing multiple time.
My code:-
var myArray = [1,2,3,4,5,6];
var i;
for(i=0;i<myArray.length;i++){
$(".Mydiv").click(function(){
alert(myArray[i]);
});
}
just example code.
Actually, I am updating every second Mydiv attr id using jQuery attr to get current user.
so when i click mydiv i should only get the current user id. but i fires all.
Thanks
If I understood you well, this is the solution:
var myArray = [1,2,3,4,5,6];
var i = 0;
$(".Mydiv").click(function(){
alert(myArray[i]);
if(i < myArray.length-1) i++;
});
Hope this helps. Cheers
You cannot fire events in a loop using .click() it is binding a handler to an event for the element or elements found for the selector. To trigger a click you use .trigger()
But in order to access the attribute of a clicked element what you need is this:
$(".Mydiv").click(function(){
alert($(this).attr('id'));
});
While you are binding to all elements in the class, the $(this) means you are only acting on the element that was clicked.
In original code ,it bind click event myArray.length times,you just need to bind once.
so you can just simply do like this:
var myArray = [1,2,3,4,5,6];
var i = 0;
$(".Mydiv").click(function(){
alert(myArray[i]);
//here change the i
i = (i+1)%length ;
});

Categories

Resources