add class to next sibling element In Javascript - javascript

How could I add toggle class? When I click on anchor tag it should add class to only next sibling element ( .treeUlChild ). i tried a lot and try to find solution but couldn't. I am new and this is my first project in javascript.
here is my html code.
<div id="treeList" class="treeDiv">
<ul class="treeUl">
<li>
GUIDELINES
<ul class="treeUlChild treeLevel2">
<li> Guidlines 1</li>
<li> Guidlines 2</li>
<li> Guidlines 3</li>
<li> Guidlines 4</li>
</ul>
<!-- End Child Ul -->
</li>
<li>
AFTER-SALES
<ul id="test" class="treeUlChild treeLevel2">
<li>xyz</li>
<li>
def
<ul class="treeUlChild treeLevel3">
<li>
ASSETS
<ul class="treeLevel4">
<li>DIGITAL</li>
<li>OOH</li>
<li>POS</li>
<li>PRINT</li>
<li>SOCIAL GIF</li>
<li>SOCIAL VIDEOS</li>
</ul>
<!-- End Child Ul -->
</li>
</ul>
<!-- End Child Ul -->
</li>
</ul>
<!-- End Child Ul -->
</li>
</ul>
<!-- End treeUl -->
</div>
This is my javascript code.
document.querySelector('#treeList ul li a').addEventListener("click", function(){
document.querySelector('.treeUlChild').nextSibling.classList.toggle('done');
});

One issue is nextSibling returns a node object, it's better you use nextElementSibling which returns an element node. The other issue is querySelector will always return the first element with the specified selector, so the changes will always be reflected on the same element whichever link you clicked. You may rather use querySelectorAll which returns all the elements as a node list, and loop through each element and apply the changes. Another thing is, it's better to use event.target to get clicked element and rather than using a selector again.
document.querySelectorAll('#treeList ul li a').forEach(elem => elem.addEventListener("click", function(){
event.target.nextElementSibling.classList.toggle('done');
}));

There is very simple way using Bootstrap by the way.
But if you want to do that with pure Javascript, you're on the right way to it.
So first, transform your query selector into a object e.g:
var el = document.querySelector('#treeList ul li a');
forEach method, querying the single object clicked in the array of multiple objects:
el.forEach(yourFunctionName());
Add functions to your elements:
<li><a onclick="yourFunctionName()" href="#"> Guidlines 1</a></li>
<li><a onclick="yourFunctionName()" href="#"> Guidlines 2</a></li>
<li><a onclick="yourFunctionName()" href="#"> Guidlines 3</a></li>
<li><a onclick="yourFunctionName()" href="#"> Guidlines 4</a></li>
ps: you can simplify this.
Structure your function:
function myFunctionName(){
document.querySelector('.treeUlChild').nextSibling.classList.toggle('done');
}

Related

Change link title with JS

how can I change the text/name(All items)of the first link using JS without adding id/classes.
<ul>
<li class="current"><a data-filter="*" href="#">All Items</a></li>
<li class="cat-item cat-item-94"> Oslavy</li>
<li class="cat-item cat-item-93">Svadby</li>
</ul>
Thanks
Grab the element with document.querySelector and then modify it's title property directly:
document.querySelector('[data-filter="*"]').title = "Banana";
<ul>
<li class="current"><a data-filter="*" href="#">All Items</a></li>
<li class="cat-item cat-item-94"> Oslavy</li>
<li class="cat-item cat-item-93">Svadby</li>
</ul>
Assuming your link that you want to change will only have its parent "current" as class and link being the first child of the parent you can try following.
window.onload = function()
{
document.getElementsByClassName('current')[0].childNodes[0].innerHTML="Hello";
}
<ul>
<li class="current"><a data-filter="*" href="#">All Items</a></li>
<li class="cat-item cat-item-94"> Oslavy</li>
<li class="cat-item cat-item-93">Svadby</li>
</ul>
Assuming that you are using jQuery, there are several ways to update the first list item, depending how your HTML was built.
If you are sure the item with the current class will always be the first :
$('ul li.current a').html('Banana');
If you prefer to rely on the order of appearance of your list item, just take the first one:
$('ul li:first-child a').html('Apple');
Notice: Be carefull not to use a too generic selector. There may be unwanted changes on your whole page. In your case, it would be better to have a clearly identifiable parent container and use it to target your list safely.

Cufon (jQuery?) selector not to select children

I have a very basic and usual list menu with a submenu:
<ul>
<li>Home</li>
<li>
About
<ul id="sub-menu">
<li>Child1</li>
<li>Child2</li>
</ul>
</li>
</ul>
And then I have a Cufon selector applying a font to the menu:
Cufon.replace('ul li a');
Is there any way to select only the first level of the menu and disregard the other? Right now both levels get the font, but I would like to use something else for submenu.
I am very much a beginner with Javascript, Cufon and jQuery, I tried using child selectors but I had no luck with that. How can I achieve this?
It appears that your JavaScript library uses CSS-style selectors; you can just use
<ul class='containingMenu'>
<li>Home</li>
<li>
About
<ul id="sub-menu">
<li>Child1</li>
<li>Child2</li>
</ul>
</li>
</ul>
with this selector
ul.containingMenu > li > a
where the > causes the selector to apply only to a's that are direct children of li's that are direct children of the ul.containingMenu.
↪ See this example in action at JSFiddle.

Finding previous and next li with Javascript

I have an uncertain amount of nested ul and li tags like:
<ul>
<li>5
<ul>
<li>2
<ul>
<li>1
</li>
<li>4
<ul>
<li>3
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>7
<ul>
<li>9
<ul>
<li>14
<li>
</ul>
<li>11
</li>
</ul>
</li>
</ul>
I'm using Kendo ui treeview and it returns me the element where the l was dropped (it might be a element inside the li because I have some spans in each one).
What I need is to know the previous and next li through DOM and Javascript to save the new order of elements.
Can anyone help please?
You didn't specify which event you were using, but it should be "dragend". That way you should be able to detect the parent li and then just get all of it's children to reorder.
Check out this fiddle here. Is this closer to what you are looking for?
http://jsfiddle.net/burkeholland/CrRUz/
Using jQuery:
var parentLi = $(e).closest('li');
var previousLi = parentLi.prev()
var nextLi = parentLi.next();
Where e is the element receiving the drop.

Toggle class on all elements EXCEPT on that's hovered jQuery

I would like to add a class to all the elements in my menu that ARE NOT being hovered over. Instead of
$('#nav li').hover(function(){$('ul',this).toggleClass('active')
I would like all the other elements in the unordered list to be changed. Any simple way?
HTML
<ul>
<li>State Level</li>
<li>National Level</li>
<li>Community Level</li>
</ul>
</li>
<li> Research</li>
<li> Contact Us
</li>
</ul>
$('#nav li').hover(function(){$('ul',this).not($(this)).addClass('blah')

How can I stop a JavaScript function from affecting a child element?

I have looked around for a solution to this problem, but it's so wonky that I doubt many people have considered it. A web application that I've recently inherited as a web administrator runs on Drupal (version 6). Unfortunately, I am unable to edit the Drupal install or create a custom theme until May due to other obligations that must be tended to first.
First off, I realize and whole-heartedly agree that there are more efficient (and elegant) ways of solving this problem, but for the time being, this is what the client wants and is comfortable with implementing.
Anyways, the old administrator was using Drupal to develop the site's navigation. The code that Drupal spits out on the HTML page is:
<ul class="menu">
<li class="expanded first">Housing
<ul class="menu">
<li class="leaf first">Housing Roster</li>
<li class="leaf">My Floor</li>
<li class="leaf">Photo Viewer</li>
<li class="leaf last">Building Maintenance</li>
</ul>
</li>
<li class="expanded">Reports
<ul class="menu">
<li class="leaf first">Build Floor Report</li>
<li class="leaf">Submit Incident Report</li>
<li class="leaf last">Submit Lockout</li>
</ul>
</li>
<li class="expanded">Office
<ul class="menu">
<li class="leaf first">Check In Package</li>
<li class="leaf">Check Out Building Package</li>
<li class="leaf">Check Out Campus Package</li>
<li class="leaf last">Check Equipment Out</li>
</ul>
</li>
<li class="expanded">Staff
<ul class="menu">
<li class="leaf first">Pre Programs</li>
<li class="leaf">Post Program</li>
<li class="leaf">Programming Database</li>
<li class="leaf last">Staff Downloads</li>
</ul>
</li>
<li class="leaf">My account</li>
<li class="leaf last">Log out</li>
The biggest concern I have with this output is that there is a ul element with the class attribute of "menu" nested inside of another ul element with the class attribute of "menu."
The goal of the JavaScript function that I am writing is to
Allow for jQuery to expand and collapse the child ul element whenever the respective li element with a class of "expanded" is clicked
Change the href attribute of ONLY the li elements with a class of "expanded" to "javascript:void(null)" so that they don't redirect the user to any page
Here is the JavaScript function that I've got going so far:
<script type="text/javascript">
$(function() {
//Hide the nested lists
$('ul.menu li.expanded ul.menu').hide();
//Change the destination of the header links
$('ul.menu li.expanded a').attr("href", "javascript:void(null)");
//Toggle the display of the nested lists
$('ul.menu li.expanded a').click(function() {
$(this).next().slideToggle('normal');
});
});
</script>
This works just fine, except it changes the href attribute of the nested li elements to "javascript:void(null)" as well. Is there a way that I can alter my JavaScript function to make sure that it applies the new href attribute ONLY to the li elements with a class of "expanded" and not to the li elements with a class of "leaf?"
At this point, I'm really only interested in an alteration of my JavaScript function. Like I said, I know and agree that there are better methods (such as altering the html output of the Drupal theme to begin with), but if I can get a quick fix in as a temporary solution while I rebuild the entire application, that would be awesome!
Please let me know if you have any suggestions!!!
THANKS!!!
Use a more specific selector:
$('ul.menu > li.expanded > a').attr( ...
The > matches only immediate children instead of all children.
If you're just trying to prevent the browser from following the href, you don't need the "javascript:void(null)". What you want to do instead is to stop the event from propagating:
$("ul.menu li.expanded > a").click(function(event) {
event.stopPropagation();
...
});
You could try
$('ul.menu li.expanded>ul.menu').hide();
This makes it apply only to the next element.
Another way would be to use
$('ul.menu li.expanded ul.menu:first').hide();
You can use the direct child selector ">".
e.g:
<script type="text/javascript">
$(function() {
//Hide the nested lists
$('ul.menu li.expanded ul.menu').hide();
//Change the destination of the header links
$('ul.menu li.expanded > a').attr("href", "javascript:void(null)");
//Toggle the display of the nested lists
$('ul.menu li.expanded > a').click(function() {
$(this).next().slideToggle('normal');
});
});
</script>

Categories