I do have a list item which looks like this:
HTML
<ul>
<li id="nav-menu-item-7" class="menu-element">
TEST 2
<ul>
<li id="nav-menu-item-8" class="menu-element">TEST 3</a></li>
<li id="nav-menu-item-11" class="menu-element">
PAGE 4
<ul>
<li id="nav-menu-item-77" class="menu-element">LINK</li>
</ul>
</li>
</ul>
</li>
</ul>
JQUERY
$(document).ready(function(){
$(document).on('click', '.menu-element', function(e){
var id = $(this).attr('id').replace(/\D/g,'');
alert(id);
});
});
I simply want to output the numeric ID of the container in an popup which i achieve with JQuery. The Problem that i am having now it that i get an Popup for the element i clicked and for the parent objects. This means in this case 77,11,7. I only want the first element to be ouput, means the 77 without having to change the whole structure of the menu. Any Ideas? Thank you.
Just stop the event propagation to the parent elements:
$(document).on('click', '.menu-element', function(e){
e.stopPropagation();
var id = $(this).attr('id').replace(/\D/g,'');
alert(id);
});
You should read about how events traverse the DOM, first from the document root to the clicked elements, then down to the document object. You can stop the propagation in both phases.
Related
I am working on To Task Project.
Here i added items dynamically and also generated items and dynamically.
But when i want to delete items by clicking on a span element.
This click doesn't work.
I search each and every solution regarding this issue but none of them meets my requirement as i want.
$("[id^=remove_]").click(function() {
alert("working");
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul id="task-list">
<li class="task" id="item_1"><span class="delete-todo" id="remove_1">X</span><span class="main-task">3232</span></li><li class="task" id="item_2"><span class="delete-todo" id="remove_2">X</span><span class="main-task">djkhjsh</span></li>
<li class="task" id="item_3"><span class="delete-todo" id="remove_3">X</span><span class="main-task">snsajdsakm</span></li><li class="task" id="item_4"><span class="delete-todo" id="remove_4">X</span><span class="main-task">sahgsabsa\</span></li>
<li class="task" id="item_5"><span class="delete-todo" id="remove_5">X</span><span class="main-task">sjghjdsn</span></li>
</ul>
I tried this.
But It is not working.
Can someone explain me why its not working.
NB: I tried several solution found on SO.
Select the remove button by class, not ID. And change the code to use .on() method that is bound to the document so all elements can be selected as following:
$(document).on('click', '.delete-todo', (function() {
alert("working");
});
Delegate events to an ancestor tag that all clickable tags have in common. By doing so, allows any tags nested within the ancestor tag to be clickable (including tags that are added dynamically later on). In order to pinpoint the clicked tag, $(this) always points to the tag the user currently clicked (in this case this = event.target = "currently clicked tag"). By using this pattern, #id is pointless and .class a more efficient and versatile selector.
Anotomy of jQuery event delegation
//$('ancestor-selector').on('event', 'target-selector', callback);
<ul class="list">
<li class="task"><b class="delete">X</b>Item</li>
<li class="task"><b class="delete">X</b>Item</li>
<li class="task"><b class="delete">X</b>Item</li>
</ul>
$('.list').on('click', '.delete', deleteTask);
Demo
Details commented in demo
/*
Delegate the click event (ie .on('click',...)) to the
ancestor tag (ie .list) of all clickable tags (ie .delete)
NOTE: callback function (ie deleteTask) does NOT have "()" because
it is called when the event is triggered. deleteTask() would be
triggered immediately (which is not desired)
*/
$('.list').on('click', '.delete', deleteTask);
/*
Although this callback function doesn't use the event object,
it is passed by default and it's just a personal habit of mine to
always include it when defining a callback/event handler.
$(this) | in this case points to the tag the user clicked
(aka event.target)
.closest('.task') | will traverse up the DOM to find the first tag
matching .task
.remove() | self explanitory
*/
function deleteTask(event) {
$(this).closest('.task').remove();
}
/*
This code is to dynamically add items to list for demonstration
purposes and is not required as part of the solution to OP question
*/
$('.add').on('click', function(event) {
$('.list').append(`<li class='task'><b class='delete'>X</b> Dynamically added list item</li>`);
});
.delete {
display: inline-block;
padding: 1px 3px;
cursor: pointer
}
<ul class="list">
<li class="task"><b class="delete">X</b> 1010</li>
<li class="task"><b class="delete">X</b> 2929</li>
<li class="task"><b class="delete">X</b> 3838</li>
<li class="task"><b class="delete">X</b> 4747</li>
<li class="task"><b class="delete">X</b> 5656</li>
</ul>
<!--
This button is to dynamically add items to list for demonstration
purposes and is not required as part of the solution to OP question
-->
<button class='add'>ADD</button>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
I tried running the code snippet which you attached.
when i just clicked on the span element 'X' click event is getting triggered
when i clicked on entire li element click event is not getting triggered because you have defined your click event only for span element
Some Alternatives to trigger click event using ID:
$("#id").click(function(){
alert('working');
})
$ul.on("mouseenter", 'li', function() {
$("li button").slideDown();
});
So I have a li with a button adjacent to it like this:
<ul>
<li>Buy Robes<button>Delete</button></li>
<li>Go shopping<button>Delete</button></li>
<li>Buy noodles<button>Delete</button></li>
</ul>
But when I hover over any particular li, buttons for all lis is shown. But I want for that particular li I hover on. Like using the this keyword.
$ul.on("mouseenter", 'li', function() {
$(this).$("li button").slideDown();
});
Obviously the above code is wrong, but I want that to work something like this.
As pointed out in comments, your HTML is invalid. buttons are adjecent to the lis, but the selector you use focuses on finding the buttons inside the lis.
Correct your HTML; put the buttons inside the lis:
<ul>
<li>Buy Robes <button>Delete</button></li>
<li>Go shopping <button>Delete</button></li>
<li>Buy noodles <button>Delete</button></li>
</ul>
Now your selector $("li button") targets the correct elements. But still, there is one more issue. You're showing all the buttons, irrespective of which li was hovered. To correct this, scope your selector with this:
$ul.on("mouseenter", 'li', function() {
$(this).find("> button").slideDown();
});
This way, only the button, whose li was hovered, will be shown.
I have a 'tree' of information that's displayed in many nested lists (ul li ul li ....). Two problems:
When I click a <li>, the parent ul is toggled as well as the child.
If I click on an <li> in a nested list that does not have a ul in it (say, Blue under Cranberry below) the parent ul is toggle, even though this shouldn't be matching 'li.has(ul)'.
I've tried various JQuery selectors, next(ul), children().first(), etc with the same results. No luck - though I'm sure I'm just missing something simple here.
On JSFiddle.
$('li.has(ul)').click(function() {
$(this).children('ul').toggle();
});
And the html:
<ul class="unstyled" id="full_ontology">
<li>Apple</li>
<li>Banana</li>
<li>Cranberry
<ul>
<li>Blue</li>
<li>Red
<ul>
<li>Round</li>
<li>Square</li>
<li>Circular</li>
</ul>
</li>
<li>Purple</li>
</ul>
</li>
<li>Date</li>
<li>Elderberry
<ul>
<li>Yellow</li>
<li>Pink</li>
<li>Black</li>
</ul>
</li>
<li>Fig</li>
</ul>
The problem is event propagation, prevent it
$('li:has(ul)').click(function (e) {
$(this).children('ul').addClass('thisOne').toggle();
});
$('li').click(function (e) {
e.stopPropagation();
});
Demo: Fiddle
It's all about propagation.
Here is the working JavaScript:
$('li').click(function(e) {
if ($(this).has('ul')) {
$(this).children('ul').addClass('thisOne').toggle();
}
e.stopPropagation();
});
JSFiddle: http://jsfiddle.net/zkFGU/3/
Basically, first you want this event on all of the list items, not just the ones that have the ul. The reason is because if you don't, you can't stop propagation. For example, "Blue" under "Cranberry" has no list, so it wouldn't call the event. However, because "Blue" is actually in Cranberry, which is a list item and does trigger the event, clicking Blue counts as clicking Cranberry, so Cranberry retracts. By giving Blue a change to chance to stop propagation, it prevents Cranberry from erroneously collapsing.
The other part of stopping propagation is simply to stop parents. We want only the element we directly clicked on (which is triggered first) and no other element to (attempt) to toggle.
I have styled a list to look like a select box and I want to fire a function when the user clicks an element in the list however the element is loaded via AJAX and hence isn't there when the page loads and I can't bind an onclick event to it onDomReady.
If I had it as a normal select list I could just tag on an onChange event to the <select> field, but I obviously can't do that in my case.
My HTML:
<div id="main_category_field" class="fields">
<div class="cat_list">
<ul>
<li class=""><a rel="1866" href="#1866">Sports Cards ></a></li>
<li class=""><a rel="1867" href="#1867">Gaming Cards ></a></li>
<li class=""><a rel="1868" href="#1868">Non-Sport Cards ></a></li>
<li class=""><a rel="1869" href="#1869">Supplies & Storage ></a></li>
<li class=""><a rel="1940" href="#1940">Video Games </a></li>
</ul>
</div>
<div class="contentClear"></div>
</div>
How can I run a function whenever the user clicks any of these options? Also would be great if you could also advise how to pass the respective value of the rel back when they click an option.
Using jQuery so options in that would be preferred.
Edit: Meant to say that the main element main_category_field is a static element. The elements inside are loaded via AJAX.
you need to delegate your elements to static parent , if the element is added dynamically using on()
try this
$(document).on('click','li a',function(e){
e.preventDefault();
var rel = this.rel;
//or using attr()
var rel=$(this).attr('rel');
alert(rel);
});
however delegating it to its closest static parent(present at a time of insertion) is better than document itself.. so if you are adding the list inside main_category_field div.. then you can use
$('#main_category_field').on('click','li a',function(e){
//same stuff
The key word is event delegation. If you want to assign event handlers to dynamically added elements for which you know their "future" selectors, you should use the .on() method on an (already existing) parent element of those dynamic elements.
The second parameter to .on() is then the selector of the dynamically added elements
$(document).on('click', '.cat_list li a', function(e) {
alert(this.rel); // show the "rel" attribute of the clicked a element
e.preventDefault(); // to prevent the default action of anchor elements
});
To bind an event handler to an element that does not yet exist on the page use on.
$(document).on("click", "#main_category_field", function(e){
e.preventDefault();
var rel = e.target.rel;
});
JS Fiddle: http://jsfiddle.net/82bAb/
Use .on for listen dynamically created dom elements as follows
$(document).on('click','div.cat_list ul li a',function(){
var rel=$(this).attr('rel');//to get value of rel attribute
alert(rel);
//other operations
});
I am trying to swap the selected class from tab to tab to display which one is current
Sample Code
$("li.selected").idTabs(function(id,list,set){
$("a",set).removeClass("selected")
.filter("[#href='"+id+"']",set).addClass("selected");
for(i in list)
$(list[i]).hide();
$(id).fadeIn();
return false;
});
so on click I am trying to remove and load the selected class with no luck, tried this
<ul class="idTabs">
<li class="selected">Request more information</li>
<li>Request a test drive</li>
<li>Make an offer</li>
<li>Get a quote</li>
</ul>
$('.idTabs li').click(function(){
$('.idTabs li').removeClass('selected');
$(this).addClass('selected');
return false;
});
Aaron, your second example seems like it should work, but only works on the first two list items for some reason. I added classes to the li's to make the selector more specific and it works fine now.
<ul class="idTabs">
<li class="navTab selected">Request more information</li>
<li class="navTab">Request a test drive</li>
<li class="navTab">Make an offer</li>
<li class="navTab">Get a quote</li>
</ul>
$('.navTab').click(function(){
$('.navTab').removeClass('selected');
$(this).addClass('selected');
return false;
});
Regarding your comment below:
It works every time when you click on an li... does not work when clicking on the anchor text because the click handler is not attached to that. You should add "display: block;" to your anchor within your li to expand the click area to the entire li (you will need to remove the padding from your li and in turn pad your 'a' so that the entire li is clickable). then... move the click handler to the anchor and have it change the parent's (li) class. I'm thinking it should go something like this (I'm not able to test it out right now):
$('.navTab a').click(function(){
$('.navTab').removeClass('selected');
$(this).parent().addClass('selected');
return false;
});
Give all your tabs a class like 'tab', then try something along the lines of this:
$('li.tab').click(function(){
$('.tab').removeClass('slected');
$(this).addClass('selected');
return false;
});
You haven't really said what the problem is, but I'm guessing your selectors aren't quite right. You seem to be passing in the "set" class as a second argument, rather than as part of the selector string.
Try:
$("a," + set).removeClass("selected")
and
.filter("[#href='"+id+"']" + set)