I have this HTML code
<ul id='something'>
<li class="listItem"><span class="name">Somename1</span> <span class="number">4</span></li>
<li class="listItem"><span class="name">Somename2</span> <span class="number">4</span></li>
<li class="listItem"><span class="name">Somename3</span> <span class="number">4</span></li>
</ul>
I also have this JavaScript code that attaches an event listener to the ul tag like this
let itemList = document.getElementById('something')
itemList.addEventListener('click', event => {
....
})
I want to use event bubbling to access the li elements but the span elements always get the event in the browser. How do I disable the event listener on the span elements? How can I use conditional statement to access only the immediate child elements of the ul tag. Is there a better way to go about this than what I'm doing? Please I'm using pure JavaScript.
Use Element.closest() on the event's target to find the closest <li> parent element (or itself if the li is clicked directly):
let itemList = document.getElementById('something')
itemList.addEventListener('click', event => {
const li = event.target.closest('li');
if (!li) return;
console.log(li);
})
<ul id='something'>
<li class="listItem"><span class="name">Somename1</span> <span class="number">4</span></li>
<li class="listItem"><span class="name">Somename2</span> <span class="number">4</span></li>
<li class="listItem"><span class="name">Somename3</span> <span class="number">4</span></li>
</ul>
You can use pointer-events css attribute to achieve this.
#something li>span {
pointer-events: none
}
Related
I've got a structure as in this fiddle: https://jsfiddle.net/Arne651/s8wbeyh5/11/
<ul id="ul">
<li class="test">
<p>
Some text
</p>
</li>
<li class="test">
<p>
Some text
</p>
</li>
<li class="test">
<p>
Some text
</p>
</li>
</ul>
I've got an event on a <ul> element, in which im trying to do something with the <li> element that was clicked. This <li> element contains a <p> element and the event doesn't seem to bubble upwards.
let ul = $("#ul")
ul.on("click", function(e) {
let clicked = $(e.target)
console.log(clicked)
if (clicked.hasClass("test")) {
console.log("li triggered")
}
})
I don't want events on all the <li> elements because the list can get quite long and a single event feels neater.
When clicking the text, the target is the p tag.
Getting the closest li might not be the best way to do this but this works.
ul.on("click", function(e) {
let clicked = $(e.target).closest('li');
console.log(clicked);
if (clicked.hasClass("test")) {
console.log("li triggered");
}
});
you can add the click on the li only try this
let li = $("#ul li.test")
li.on("click", function(e) {
console.log("li triggered");
})
I am first fetching all li that have calse test then add the listener on them.
I have the following example code:
<ul class="name_of_class" id="TEST">
<li class="foo">1</li>
<li class="boo">2</li>
<li class="goo">3</li>
<ul>
When a specific <li> is selected, the class changes to whatever the name is, plus sortUp or sortDown.
Example:
<ul class="name_of_class" id="TEST">
<li class="foo">111</li>
<li class="boo sortDown">222</li>
<li class="goo">333</li>
<ul>
I am trying to get the value of the actual text inside the <li>, but I keep getting undefined.
var li = document.getElementById('TEST');
alert($('#TEST').filter('.sort').html());
I tried using different ways but no matter what I do I can't get the actual value, which in this case should be 222.
Any idea what I am doing wrong?
You can select the li with either sortUp or sortDown by using the [attribute*="value"] selector,
The [attribute*="value"] selector is used to select elements whose
attribute value contains a specified value.
const li = document.querySelector('[class*="sort"]');
console.log(li.textContent);
li.style.background = "red";
<ul class="name_of_class" id="TEST">
<li class="foo">111</li>
<li class="boo sortDown">222</li>
<li class="goo">333</li>
<ul>
See css attribute selectors
I'm not sure what the classes have to do with your requirement to get the text of the clicked li element. Just set up a click event handler on the ul and then in the handler, check the event target to ensure it was an li, then just get the text of the event target.
document.getElementById("TEST").addEventListener("click", function(evt){
if(evt.target.nodeName==="LI"){
alert(evt.target.textContent);
}
});
<ul class="name_of_class" id="TEST">
<li class="foo">1</li>
<li class="boo">2</li>
<li class="goo">3</li>
<ul>
Maybe you can try this:
alert($('#TEST').find('li[class^='sort']').html());
You will find a li element that has a class that starts with "sort".
You can see more of this selector here.
HTML code
<ul id='orgCat'>
<li parent-id="0" li-id="16">Anthropology Department</li>
<li parent-id="16" li-id="18">Anthropology Faculty Collections</li>
<li parent-id="16" li-id="23">Shared Collections</li>
<li parent-id="0" li-id="19">Center for Research on Vermont</li>
<li parent-id="19" li-id="24">Collections for Testing</li>
<li parent-id="24" li-id="25">Geology Department</li>
</ul>
Jquery
jQuery(function($){
var $ul = $('ul');
$ul.find('li[parent-id]').each(function () {
$ul.find('li[parent-id=' + $(this).attr('li-id') + ']').wrapAll('<ul />').parent().appendTo(this)
});
});
//to get li-id on double click
$('#orgCat li').dblclick(function(){
alert($(this).attr('li-id'));
})
Problem is
When double click on 'li' element its showing parents 'li-id' also but it should return only current list 'li-id'. Jsfiddle
You need to use e.stopPropagation to stop event bubbling.
$('#orgCat li').dblclick(function(e){
e.stopPropagation();
alert($(this).attr('li-id'));
});
Check this link for more information.
I'm new to javascript and I wanted to create an event onclick to list items. The problem is that I want to create an event to the li tag, but it keeps firing when I click the descendent ul's.
Here goes part of my code:
<li id="1660761" class="HTMLFirstLevel HTMLHorizontalArrowDown">
<ul id="ul1223945" class="HTMLItem">
<li id="1490659" class="HTMLRemainingLevels"></li>
<li id="483463" class="HTMLRemainingLevels"></li>
<li id="80919" class="HTMLRemainingLevels"></li>
<li id="1280053" class="HTMLRemainingLevels"></li>
<li id="1799353" class="HTMLRemainingLevels"></li>
<li id="1882209" class="HTMLRemainingLevels"></li>
<li id="462917" class="HTMLRemainingLevels"></li>
</ul>
</li>
<li id= ......>
<ul....>
<ul...>
</li>
and my javascript:
var parentNode = document.getElementById('1660761');
parentNode.addEventListener("click",function(e) {
alert('Hi There');
});
}
Now I only want it to fire on the item li with the id 1660761, and not the items inside the list.
The list is an imported component and I can't create events inside the html, that's why I'm accessing it outside with javascript.
Now here's how I've done it by scaning the div by tag name and then adding a "click" event listener if the content equals the tag inner html that I was searching for.
I leave the rest of the html that it's important to this aproach:
<div id="MainMenu" class="HTMLMenuContainer HTMLMenuHorizontal">
<ul id="ul1351387" class="HTMLMenu">
<li id="1660761" class="HTMLFirstLevel HTMLHorizontalArrowDown">
<a href="#">
<span>Back Office</span>
</a>
<ul id="ul1172716" class="HTMLItem">
<li id="1490659" class="HTMLRemainingLevels">
<a href="#">
<span>
Some submenu Here
</span>
</a>
</li>
.....
and the code:
var divs = document.getElementsByClassName('HTMLMenuHorizontal');
var span = divs[0].getElementsByTagName('span');
//I iterate till 19 cause its more than all the spans in the page.
for(var i=0; i<20; i++) {
var sp= span[i];
if(sp.innerHTML==('Back Office')){
sp.addEventListener("click",function back(){
//do something here like
alert('Back Office');
});
}
}
This works fine and it doesn't fire on the itens inside.
This works because in my case the itens doesn't change the content, only the visibility.
I do the same for all the other itens that have descendents.
Thank you all.
Below is my jQuery code for this problem:
$(function(){
$("li.1660761").live("click", onListItemLink);
}
function onListItemLink(){
alert('Hello World!');
}
This one is for JavaScript:
var parentNode = document.getElementById('1660761');
parentNode.onclick = onListItemLink;
function onListItemLink(){
alert('Hello World!');
}
take a look at this page to undersand correctly:
capture event
and what's function(e-->??)
I hope it helps.
$('#1660761').unbind('click').click(function(e) {
if (e.target !== this) return;
alert('Hey There!');
});
Try This code : http://jsfiddle.net/sd5LZ/
I have the following code structure:
<ul class='menu'>
<li>
Main Menu
<ul class='hide'>
<li>SubMenu1</li>
<li>SubMenu2</li>
</ul>
</li>
<li>
Main2
<ul class='hide'>
<li>Sub1</li>
</ul>
</li>
</ul>
Is there a way for me to have a jQuery click event on Main Menu and Main2 in a generic way that will remove the class 'hide' of the correct children each time?
Here is another way, which uses event delegation and only runs when the li element and not its children was clicked:
$('ul.menu').on('click', 'ul.menu > li', function(e) {
if(e.target === this) {
$(this).children('ul').toggleClass('hide');
}
});
DEMO
$("ul.menu > li").on("click", function () {
$(this).children("ul").removeClass("hide");
});
Example: http://jsfiddle.net/dpkBL/
Dont always do what the crowd tells you, at least think about it for a while!
I bet people will recommend you to use a selector such as ul.menu > li, but please remember that this will not only trigger a click event when you click on the text "Main Menu", but also when you click on any of the other content inside the matching li.
If you'd like to implement a show/hide toggle you are far better off wrapping the text "Main Menu" inside it's on element, and then use something as the below to alter what you may want to alter.
$(<main menu text selector>).siblings (<siblings selector>);
Still want/have to follow the crowd?
If this is the case I'd recommend you to at least do it with a little twist to prevent what I previously described.
(edit: revised version after reading the jquery documentation for elements)
$('ul.menu > li').click (function(e){
if (e.target === this) {
$(this).children ('.hide').removeClass ('hide');
}
});
$("ul.menu > li").click (function () {
$(this).find ('.hide').removeClass ('hide');
});
$("ul.menu > li > *").click (function () {
return false; // prevent event from bubbling up
});
Sample implementation of recommended version
The below will bind a click-event-listener to .menu-toggle, when the event is fired the siblings (ie. the tags who are in the same scope as the clicked .menu-toggle) matching .hide will have their class="hide" removed.
Javascript
$(".menu-toggle").click (function () {
$(this).siblings ('.hide').removeClass ('hide');
});
HTML
<ul class='menu'>
<li>
<span class="menu-toggle">Main Menu</span>
<ul class='hide'>
<li>SubMenu1</li>
<li>SubMenu2</li>
</ul>
</li>
<li>
<span class="menu-toggle">Main2</span>
<ul class='hide'>
<li>Sub1</li>
</ul>
</li> </ul>
Take a look at the child selectors. I think that is what you want.
$('.menu > li').click(function () {
$(this).children('ul').removeClass('hidden');
});