Iterate through elements, adding click event to each of them - javascript

jQuery newbie here.
If I have this html:
<ul id="floor-selector">
<li id="floor-1">Ground Floor</li>
<li id="floor-2">Second Floor</li>
<li id="floor-3">Third Floor</li>
<li id="floor-4">Premier Floor (Premier Floor)</li>
</ul>
I want to add a click event to each li item, such that I can get the id of the element I am on. Right now I just have an alert with the index I'm on (and it's not working either), but I really want the ID of the item I'm on, not the index of the array returned by my selector.
Here's what I tried, but it doesn't seem to work, I think I might have the wrong understanding of each() or click().
$('#floor-selector li').each( function(index, node) {
node.click( function(){ alert('I am on the '+index+'th element'); } );
// but I really want to get the ID of this element
});

This should work:
$('#floor-selector li').on('click', function() {
alert('I am the '+$(this).attr('id')+' element');
});
Behind the scenes jQuery does a bunch of magic and essentially binds the function you pass to the element. this therefore references the element that you are clicking and passing it to jQuery functio: $(this) gives you back that element wrapped in a jQuery object. Of course you could simply access the id on this directly.

Related

JQuery: adding event handler (animation) on dynamically created element

I need to get a dynamically created list item within unordered list to simultaneously be animated while being created.
My JQuery code setup:
$("button#enterAction").click(function(){
var userAction = $('input#action').val();
$("ul.list-group").append('<li class="list-group-item" id="added-list-item">'+userAction+'</li>');
});
Now this code above creates a list item without animation to it. How do I add animation (say .toggle or .animate) to only this list item without affecting my whole unordered list?
I thought it could be achieved by firing a second event on dynamically created element with an ID added-list-item but I am not sure how to correctly write it down (syntax and functions used). Please help.
You can add a hidden element and then fade it out:
$("ul.list-group").append('<li class="list-group-item" style="display:none">'+userAction+'</li>').children(':last').fadeIn();
Working example:
$(function() {
$("button#enterAction").click(function(){
var userAction = $('input#action').val();
$("ul.list-group").append('<li class="list-group-item" style="display:none">'+userAction+'</li>').children(':last').fadeIn();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="action">
<button id="enterAction">Add</button>
<ul class="list-group"></ul>
There are two ways of binding events Direct and Delegated. You are using the direct method which applies on existing elements only. To let event listener work on dynamic elements you'll need to use the second method.
Direct method: $(selector).click(callback);
Delegated method: $(selector).on('click', callback);
Delegated method will work for you.
you could bind click to your new created item.
here is an example
$("button#enterAction").click(function(){
var userAction = $('input#action').val();
var li = $('<li class="list-group-item" id="added-list-item">'+userAction+'</li>'); // create li
li.bind("click", function(){
/// code goes here
})
$("ul.list-group").append(li);
});

jQuery - Setting occurences of a class to their respective data on click

what I want to achieve is setting all occurences of a class to their designated data - except the particular occurence clicked, which is to be set to something unique. My code below gives an undefined error on the "y" variable. How would I go about contextualizing the dataset?
<div id="menu">
<ul>
<li id="menu-tos" data-info="TERMS OF SERVICE">TERMS OF SERVICE</li>
<li id="menu-contact" data-info="CONTACT">CONTACT</li>
<li id="menu-signup" data-info="SIGN UP">SIGN UP</li>
<li id="menu-login" data-info="LOG IN">LOGIN</li>
</ul>
</div>
<script>
$('#menu ul li').click(function() {
i = $(this.id);
y = dataset.info;
$('#menu ul li').not(i).html(y);
$(i).html('Something unique');
});
</script>
(to skip the explanation and see a working version, scroll to the bottom)
Your undefined error is because you trying to access dataset as if it is a variable, when it is actually a property of DOM element objects (details here).
Also, if I'm understanding your desired functionality correctly, there are a couple other issues you'll run into with your code:
i = $(this.id); this will resolve to $('menu-tos'). To select via ID, you'd need a #, like this: $('#menu-tos'). In your case, though, there's really no reason to set the current element to a variable anyway, because it is already available via $(this).
As mentioned above, y = dataset.info; won't work because dataset is a property on HTML Element objects, not a variable. Since you're using jQuery, it'd be easier to use $(this).data('info').
$('#menu ul li').not(i).html(y); this will not do what you said you're trying to do. This will set the HTML of all other <li> elements to the value of the one you just clicked. To set each one to its own value, you'll need to loop through them using .each()
$(i).html('Something unique'); assuming i was set correctly as a jQuery object, you don't need the jQuery wrapper here, you can just use i.html('Something unique');
A couple other things that would help your code:
The way you are setting your variables now (without using var), it will set them on the global scope. This may work, but it can cause collisions, and is generally avoided. Use var like var i = $(this);, and it will keep that variable only within the scope of your click() function.
When using jQuery, you should wrap your code in a $(document).ready() callback. This will ensure that the DOM is loaded before jQuery tries to bind any event handlers (such as your click handler).
After fixing the issues mentioned here, the javascript code ends up looking like:
$(document).ready(function() { // ensure document is loaded before running code
$('#menu ul li').click(function() {
// set all other elements to their own data-info attribute value
$('#menu ul li').not(this).each(function() {
var info = $(this).data('info');
$(this).html(info);
});
// set the clicked item to 'Something unique'
$(this).html('Something unique');
});
});
Checkout the working code on this JSFiddle.
Try like this:
$('#menu ul li').click(function() {
$(this).siblings().each(function() {
var info = $(this).data('info');
$(this).html(info);
});
$(this).html('Something unique');
});
Full example here https://jsfiddle.net/_jakob/q49kq3c5/1/

Using jQuery .remove() to take <li> elements out of an <ol> but the DOM still thinks that the <li> elements are there?

I have a function that removes li elements from an ol when you click on an icon. When the ol is totally emptied, I would like to replace the li with a bit off filler material so that the user can still drag and drop new li elements into the list. (It's kind of a shopping cart setup.)
The problem that I'm running into is that when I use jQuery .remove() the li is removed from the DOM BUT jQuery doesn't it as being gone. So, for example, calling .has(".li") returns true even when all the li's are gone, and calling childNodes.length returns the total number of li that have ever existed in the ol. Code follows:
function onClick(element)
var parent = $(element).parent().attr('id');
$(element).remove();
var container = document.getElementById(parent);
console.log(container.childNodes.length); //always logs the total number that have ever existed
if(container.childNodes.length < 1){
parent.append("<li class='placeholder'>Drag and Drop Components Here</li>");
I'm pretty sure that this isn't the problem because I've been careful to grab the parent container only after the element was removed from the DOM.
Any ideas?
EDIT: The requested ul and li structure:
<h4>Components</h4>
<ol id="components" class="droppable">
<li class="placeholder">Drag and Drop Components Here</li>
</ol>
Users drag and drop the following code into the list, which is retrieved via $.get from some php scripts.
<li id="$id"><table style="color:white"><tr><td>$this->longname</td>
<td>Delete image</div></td></tr></table></li>
The click handler is the code above.
Assuming you have misplaced the function name onClick instead of destrComp, there are multiple problems.
To the click handler you are passing the clicked anchor element not the li element as you as assuming, so when you say $(element).parent() or $(element).remove() it is not dealing with the elements you think it is dealing.
Try
function destrComp(element) {
var $parent = $(element).closest('ul');
$(element).closest('li').remove();
if ($parent.children().length < 1) {
$parent.append("<li class='placeholder'>Drag and Drop Components Here</li>");
}
}
According to your code you seem to be removing the "a" tag, but not the parent.
$(element).remove(); //This removes the a tag
$(element).parents('li').remove(); //This removes the parent li element

prototype js library beginner

I have a list in which I am dynamically adding the classname, now when I click on that item again the class stays there. I dont want that I want that classname to be assigned to the currently clicked list item.
<ul id="menubar">
<li>one</li>
<li>two</li>
</ul>
Now when I click on one I dynamically add classname, and when I click on two the classname stays the same on one and it gets affected on two as well. but I want it to be removed from one and to be applied to currently clicked item.
How can I achieve it?
$$('#menubar li').invoke('observe', 'click', (function(e) {
//removes classname from all the li elements
$$('#menubar li').invoke('removeClassName', 'myClass');
//Gets the li you clicked on
var list_item = Event.element(e);
//adds the classname
list_item.addClassName('myClass');
}).bindAsEventListener(this));
You need to be including .removeClass() in the same event as when you addClass() to the other one.
$('.one').click(function(){
$(this).addClass('myClass');
$('.two').removeClass('myClass');
});
This could be written more efficiently, but im writing this in between meetings.
Hope it's a start!

Jquery select all children within children

I'm sure this will be a simple question but I still struggle with DOM selectors in Jquery so here is a model of my html code:
<fieldset class="product-options" id="product-options-wrapper">
<ul class="options-list">
<li><a href>Item1.1</a></li>
<li><a href>Item1.2</a></li>
<li><a href>Item1.3</a></li>
</ul>
...other html items here
<ul class="options-list">
<li><a href>Item2.1</a></li>
<li><a href>Item2.2</a></li>
<li><a href>Item2.3</a></li>
</ul>
</fieldset>
Now how do I select all of the 'li a' items in both lists (or X number of lists) with class name .options-list and bind them with a click function.
Currently I have:
$('fieldset#product-options-wrapper ul.options-list > li a').bind('click', function(e) {
//code here
});
And it only gets the first options-list.
Thanks, greatly appreciated!
EDIT: If i click on a Item2.X list item first, then it will grab that options list. But as soon as I click on the Item1.x list items it disregards the second .options-list
If you are going to bind to each li element, you should bind it to the ul element instead (helps greatly with performance when there are a lot of events).
$('.options-list', '#product-options-wrapper').bind('click', function(e)
{
e.preventDefault();//In case you don't want to go to a different page
var clicked = e.target;//The href that was clicked
/* If you only want this to happen if the a tag was clicked, add the following line
if(clicked.tagName == 'A')*/
//Rest here
});
How about $('.options-list a').bind('click', function(e) { });?
You can use delegate in this case to make it even simpler. Try this
$('#product-options-wrapper ul.options-list').delegate('li > a', 'click', function(e) {
//code here
});
Your method seems sound to me. I created a test fiddle using your HTML (and an extra anchor to prove that it won't get the click added) and your JS (with minor modifications).
http://jsfiddle.net/chrisvenus/esZxH/1/
The selector you had did work but since you said you wanted the a to be a direct child of the li (or at least I read it that way) I slightly tweaked it in my version above. ARe you sure its not just your function is not doing quite what you want while executing or can you confirm that your click function isn't being run at all?

Categories