I'm still struggling with this question.
Add an Event Handler to the li element and console.log() the name of the shirt they selected. Use JavaScript
<h3>Shirts</h3>
<ul id='list'>
<li>Biker Jacket</li>
<li>Mens Shirt</li>
</ul>
If i get your question right, use jQuery:
$('li').click(function() {
console.log($(this).text());
});
It looks like this is a homework question. And that you are new to StackOverflow.
On StackOverflow you should always write pieces of code that you have attempted.
Anyways, because you are new... I can show you 2 ways of accomplishing this.
Please note that I am not so good in vanilla Javascript aswell. So
there is probably a better way to accomplish what you're trying.
1) Inline Event Handler
You can add inline event handlers directly to the HTML, like this:
<h3>Shirts</h3>
<ul id='list'>
<li onclick='console.log(this.innerText)'>Biker Jacket</li>
<li onclick='console.log(this.innerText)'>Mens Shirt</li>
</ul>
2) Non-inline Event Handler
The difference here is that you need to refer to the exact elements you want to add an Event Listener to. The benefit of doing this, is that you don't have to add an Event Listener manually to each list element. So the HTML stays clean.
var list = document.getElementById("list"); // select the parent element
var items = list.getElementsByTagName("li"); // select all <li> items in this parent element
for (var i = 0; i < items.length; i++) { // loop through all items
items[i].addEventListener("click", function() { // add the click event listener to the item
console.log(this.innerText); // console.log() the item's text.
});
}
Also read the following MDN documentations to learn about the used functions:
getElementById
getElementByTagName
Loops and iterations
innerText
Happy learning!
Related
This is the first time I’ve thought about moving my events outside of the normal HTML onClick=”” event but I cant seem to find any references as to how I would do this with a li list.
Basically I’m trying to get the number associated with the scrollToArtical(#) in to myElement.onclick. How would you rewrite this so that the event is in the .js file.
I’ve tried variations of to get at the element but these don’t work:
var objScrollToNav = document.getElementById("id_ScrollToNav").children;
var objScrollToNav = document.querySelector("#id_ScrollToNav a");
Any help would be greatly appreciated – CES
My old code is:
<ul id="id_ScrollToNav" role="list">
<li class="sectionNavOff"><a onclick="scrollToArticle(0)" role="link">•</a></li>
<li class="sectionNavOn"><a onclick="scrollToArticle(1)" role="link">•</a></li>
<li class="sectionNavOff"><a onclick="scrollToArticle(2)" role="link">•</a></li>
</ul>
Use document.querySelectorAll to get an array-like list, then loop over them. To keep a reference to the index, make sure you also pass the index into a new closure (the addEvent function below creates a new closure).
function scrollToArticle(index) { console.log("Scrolling to:", index); }
// Select all the elements.
var links = document.querySelectorAll("#id_ScrollToNav a");
// This function adds event listener, and holds a reference to the index.
function addEvent(el, index) {
el.addEventListener("click", function() {
scrollToArticle(index);
});
}
// Loop over the elements.
for (var i = 0; i < links.length; i++) {
addEvent(links[i], i);
}
<ul id="id_ScrollToNav" role="list">
<li class="sectionNavOff"><a role="link">•</a></li>
<li class="sectionNavOn"><a role="link">•</a></li>
<li class="sectionNavOff"><a role="link">•</a></li>
</ul>
Since your li elements can be gathered up into an array and arrays have indexes, you really don't need to pass a hard-coded number to your function. You can just pass the index of the li that is being clicked to the function.
Also, don't use <a> elements when they are not directly navigating you anywhere. This can cause problems for people who use screen readers. Instead, set up the click event directly on the li elements and eliminate the a elements completely.
Lastly, don't use inline HTML event attributes (onclick). That is how we did event handlers 20 years ago and, unfortunately, this technique just won't die. There are many reasons not to use them. Instead, follow modern standards and separate your JavaScript from your HTML.
// Get all the li elements into an array
var items = Array.prototype.slice.call(document.querySelectorAll("#id_ScrollToNav > li"));
// Loop over the list items
items.forEach(function(item, index){
// Assign each item a click event handler that uses the index of the current item
item.addEventListener("click", function(){ scrollToArticle(index) });
});
// Just for testing
function scrollToArticle(articleNumber){
console.log(articleNumber);
}
#id_ScrollToNav > li {
cursor:pointer;
}
<ul id="id_ScrollToNav" role="list">
<li class="sectionNavOff" role="link">•</li>
<li class="sectionNavOn" role="link">•</li>
<li class="sectionNavOff" role="link">•</li>
</ul>
To add to the above, use data- attributes to separate css styles from javascript (meaning, html class tags should be used for html/css things only).
<li data-element="sectionNavOff">
<li data-element="sectionNavOn">
There are some minor downsides to using data- tags, mainly speed, but many enterprise applications and frameworks (e.g. Bootstrap) tend to believe the upside to separating styles from javascript completely outweighs the downsides. If I knew whether or not you use jQuery I could give you a detailed usage example.
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);
});
I made a table out of a simple list structure:
<html>
<body>
<ul id="Column:0">
<li id="Row:0></li>
<li id="Row:1></li>
<li id="Row:2></li>
<li id="Row:3></li>
<li id="Row:4></li>
</ul>
<ul id="Column:1">
<li id="Row:0></li>
<li id="Row:1></li>
<li id="Row:2></li>
<li id="Row:3></li>
<li id="Row:4></li>
</ul>
<ul id="Column:2">
<li id="Row:0></li>
<li id="Row:1></li>
<li id="Row:2></li>
<li id="Row:3></li>
<li id="Row:4></li>
</ul>
</body>
</html>
Now I want to add a simple .mouseover() to every row, for e.g. changing the color of a row, when hovered. And this is what I figured out, so far:
for (var i = 2; i <= _totalRows; i++) {
var row = $('#TimeTable ul li:nth-child(' + i + ')')
row.each(function() {
$(this).click(function(evt) {
var $target = $(evt.target);
console.log($target.nodeName)
if (evt.target.nodeName == 'DIV') {
console.log(evt.parent('li'));
}
}); //end $(this).click(fn)
}); // end each(fn)
}
I get a set of all <li> objects matching to :nth-child(i) where i is the rows number.
var row = $('#TimeTable ul li:nth-child(' + i + ')')
Now I just iter this set through to add a .click(fn) to every <li>.
This works fine. Every cell has it's .click(fn) attached to it.
But the following, what to do on a click, is where I'm stuck for several hours now:
var $target = $(evt.target);
console.log($target.nodeName)
if (evt.target.nodeName == 'DIV') {
console.log(evt.parent('li'));
}
I simply don't get it to run.
You can actually ignore this gibberish, as it's just the last of several things I already tried here.
What I'm trying to do is simply select every <li> with an id='Row:X' and manipulate its CSS. The best I yet had was, that I can click a cell, but no matter in what row this cell is, the last one gets colored. I remember having used i as the row-index, when that happened, so I might miss some understanding of event-handling here, too.
Use a class name for duplicate groups of elements not an ID. If you give row one a class of "Row1" the selector is simply:
$('.Row1')
Then:
$('#TimeTable li').removeClass('highlight');
$('.Row1').addClass('highlight');
If you just wish to change the color on mouseover:
$('#TimeTable ul li').mouseover(function(){
$(this).css('background','red');
});
$('#TimeTable ul li').mouseout(function(){
$(this).css('background','green');
});
Make your ID's like so: C1R1 (Column1Row1) and so on
JQuery read/google up "jquery each"
JQuery read/google up "jquery bind click"
JQuery read/google up "jquery attr" and "JQuery val()"
This will give you the knowledge to write your own and most importantly understand it better. You will want to achieve the following (your close but no for loop required):
A list which JQuery attaches a click event handler to each LI, and then when the click happens the ID can be retrieved.
PS. There's a time and place for tables, they 9/10 times nearly always better for displaying data than CSS is. If you have a complex multi column row and want fiexed hights and no JS to fix things or do anything smart you can have a table and css :Hover on TR for stying mouse over and out etc. Heights are also constant.
PS. PS. If your data is dynamic and coming from a database and the whole row is an ID from the database I tend to avoid using the html ID attribute for this and make my own. You can retrieve this via attr("myattribute");
NOTE ON CSS and IDS:
Standard practice for ID's are to be used once on a page.
Class for repeatable content
Good luck.
I am almost a noob at JavaScript and jQuery, (so I apologize if I didn't recognize a suiting answer to my question, in similar posts).
Here is the thing. I have a list with lots of stuff in each list item:
<ul id="fruit_list">
<li>
<h4> Fruit 1: remove </h4>
<p> blablabla </p>
</li>
<li>
<h4> Fruit 2: remove </h4>
<p> blablabla </p>
</li>
</ul>
add
What I want to do, is when I click on the anchor 'remove', to remove the list item containing it.
(Optionally I would like to manipulate the incremental number at Fruit 1, Fruit 2 etc, in a way that when I remove item #2, then the next one becomes the #2 etc. But anyway.)
So here is what I've written so far:
$(function(){
var i = $('#fruit_list li').size() + 1;
$('a.add').click(function() {
$('<li><h4>Fruit '+i+':<a href="#" class="remove">
remove</a></h4><p>Blabla</p></li>')
.appendTo('#fruit_list');
i++;
});
$('a.remove').click(function(){
$(this).parentNode.parentNode.remove();
/* The above obviously does not work.. */
i--;
});
});
The 'add' anchor works as expected. The 'remove' drinks a lemonade..
So, any ideas?
Thanks
EDIT: Thanks for your answers everybody!
I took many of your opinions into account (so I won't be commenting on each answer separately) and finally got it working like this:
$('a.remove').live('click', function(){
$(this).closest('li').remove();
i--;
});
Thank you for your rapid help!
The a.remove event binding needs to be a live http://api.jquery.com/live/ binding. The nodes are added to the DOM after doc ready is called.
Additionally, I think you want to use parent() instead of parentNode. Unless I'm behind on my jQuery, parentNode is just DOM manipulation and there's no standard remove(), it's removeChild(). Here you need a jQuery collection returned from parent().
Try $(this).parents("LI").remove();
The reason is that $('a.remove') is only executed once, and so only found at the moment you don't have any remove links yet. To solve this rewrite your ADD function like this:
$('a.add').click(function() {
var $li = $('<li><h4>Fruit '+i+':<a href="#" class="remove">
remove</a></h4><p>Blabla</p></li>');
$li.appendTo('#fruit_list');
$li.find('a.remove').click(function() {
$li.remove();
i--;
});
i++;
});
And just remove your old remove function.
EDIT: Oh, this will only work for items you add, if you already load some list items in the html before any Javascript is executed add this function under the $('a.add').click:
$('a.remove').click(function(){
$(this).parent().parent().remove();
i--;
});
Okay, so i have the following html added to a site using javascript/greasemonkey.
(just sample)
<ul>
<li><a id='abc'>HEllo</a></li>
<li><a id='xyz'>Hello</a></li>
</ul>
and i've also added a click event listener for the elements.
All works fine up to this point, the click event gets fired when i click the element.
But... i have another function in the script, which upon a certain condition, modifies that html,
ie it appends it, so it looks like:
<ul>
<li><a id='abc'>Hello</a></li>
<li><a id='xyz'>Hello</a></li>
<li><a id='123'>Hello</a></li>
</ul>
but when this is done, it breaks the listeners i added for the first two elements...
nothing happens when i click them.
if i comment out the call to the function which does the appending, it all starts working again!
help please...
Any time you set the innerHTML property you are overwriting any previous HTML that was set there. This includes concatenation assignment, because
element.innerHTML += '<b>Hello</b>';
is the same as writing
element.innerHTML = element.innerHTML + '<b>Hello</b>';
This means all handlers not attached via HTML attributes will be "detached", since the elements they were attached to no longer exist, and a new set of elements has taken their place. To keep all your previous event handlers, you have to append elements without overwriting any previous HTML. The best way to do this is to use DOM creation functions such as createElement and appendChild:
var menu = pmgroot.getElementsByTagName("ul")[0];
var aEl = document.createElement("a");
aEl.innerHTML = "Hello";
aEl.id "123";
menu.appendChild(aEl);
As an variant, you can add such html, which will work without addEventListener:
<ul>
<li><a id='abc' onclick='myFunc()'>Hello</a></li>
<li><a id='xyz' onclick='myFunc()'>Hello</a></li>
// The following add dynamically
<li><a id='123' onclick='myFunc()'>Hello</a></li>
</ul>
U can also use jQuery's 'live' function