Dropdown identification - javascript

I have two dropdown options:
<ul class="menu">
<li hidden class="inicio"><a href "#">Inicio</a>
</li>
<li class="dropdown">
OPTION 1<b class="caret"></b>
<ul class="dropdown-menu">
<li class="bd-ric">Option 1.1
</li>
<li>Option 1.2
</li>
</ul>
</li>
<li class="dropdown">
OPTION 2<b class="caret"></b>
<ul class="dropdown-menu">
<li class="bd-ric">Option 2.1
</li>
<li>Option 2.2
</li>
</ul>
</li>
</ul>
When i tried to create the Javascript to toggle it, they both opened:
$('.dropdown-toggle').click(function() {
$('.dropdown-menu').toggle();
})
Should I create a function and invoke it on the html or can I call the toggle event for a specific id?

You can use jQuery's next method:
$('.dropdown-toggle').click(function() {
$(this).next('.dropdown-menu').toggle();
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul class="menu">
<li hidden class="inicio"><a href "#">Inicio</a>
</li>
<li class="dropdown">
OPTION 1<b class="caret"></b>
<ul class="dropdown-menu">
<li class="bd-ric">Option 1.1
</li>
<li>Option 1.2
</li>
</ul>
</li>
<li class="dropdown">
OPTION 2<b class="caret"></b>
<ul class="dropdown-menu">
<li class="bd-ric">Option 2.1
</li>
<li>Option 2.2
</li>
</ul>
</li>
</ul>

Related

How to extract specific text from a html tag that is dynamically placed in the code

I want to extract a specific text which is located between the <li></li> tags in the navigation bar of a html page, but the code's not consistent. The order of the navbar elements changes depending on the conditions that I'm unable to predict. The only thing that doesn't change in the code is the <li></li> tags where the text I want to extract is embedded.
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li class="active">Homepage</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
aria-expanded="false">Menu - 1<span class="caret"></span></a>
<ul class="dropdown-menu">
<li>Menu - 1 - Option - 1</li>
<li>Menu - 1 - Option - 1</li>
</ul>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
aria-expanded="false">Menu - 2<span class="caret"></span></a>
<ul class="dropdown-menu">
<li>Menu - 2 - Option - 1</li>
<li>Menu - 2 - Option - 2</li>
<li role="separator" class="divider"></li>
<li>Menu - 2 - Option - 3</li>
<li>Menu - 2 - Option - 4</li>
</ul>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
aria-expanded="false">Menu - 3<span class="caret"></span></a>
<ul class="dropdown-menu">
<li>Menu - 3 - Option - 1</li>
<li>Menu - 3 - Option - 2</li>
</ul>
</li>
<!-- The element I need to access -->
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
aria-expanded="false">
------->[TEXT I WANT TO EXTRACT]<-------
<span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li>My Account</li>
<li role="separator" class="divider"></li>
<li class="dropdown-header">Help</li>
<li>Contact Us</li>
<li>Logout</li>
</ul>
</li>
<!-- The element I need to access -->
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
aria-expanded="false">Menu - 5<span class="caret"></span></a>
<ul class="dropdown-menu">
<li>Menu - 5 - Option - 1</li>
<li>Menu - 5 - Option - 2</li>
<li>Menu - 5 - Option - 3</li>
</ul>
</li>
</ul>
</div>
So, the following <li></li> tags of the code never changes, but its placement in the navbar changes:
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
aria-expanded="false">
------->[TEXT I WANT TO EXTRACT]<-------
<span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li>My Account</li>
<li role="separator" class="divider"></li>
<li class="dropdown-header">Help</li>
<li>Contact Us</li>
<li>Logout</li>
</ul>
</li>
When I try to extract the text using querySelector from JavaScript, it sometimes doesn't work because the <li></li> element is no longer the fifth one in the list. Thus, the selector doesn't match:
document.querySelector('li.dropdown:nth-child(5) > a:nth-child(1)');
What would be the safest way for me to extract this text?
Maybe you can give a class to the li that you want to extract and then select that class using querySelector.
Here I am assuming you want to select the logout list element.
------->[TEXT I WANT TO EXTRACT]<-------
<span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li>My Account</li>
<li role="separator" class="divider"></li>
<li class="dropdown-header">Help</li>
<li>Contact Us</li>
<li class="logout">Logout</li> //Here I have given a class 'logout'
</ul>
</li>
Select that li element using querySelector
let text = document.querySelector('.logout').innerText;
Using the filter method to find the right element is the solution to my issue. I just check whether the children of the specified tags contain a particular text that the element I want to access has. Then, I simply extract the text like the following:
// Retrieve all children inside of the navbar
Array.from(document.querySelectorAll(".nav > li.dropdown"))
// Filter the child that contains the text
.filter((el) => el.textContent.includes("Logout"))[0]
// Extract the text from the child tag
.querySelector("a").textContent.trim();

Add class to ancestor element based on existence of element in the hierarchy

I have a sample code below
<li class="treeview">
<a href="#"><i class="fa fa-link"></i> <span>Multilevel</span>
<span class="pull-right-container">
<i class="fa fa-angle-left pull-right"></i>
</span>
</a>
<ul class="treeview-menu">
<li class="active">Link in level 2</li>
<li>Link in level 2</li>
</ul>
</li>
If one of the li has a class active how can I also add a class active on the parent li or this part
<li class="treeview">
You can use jquery to achieve this. Please find the snippet below.
$('.treeview-menu li').on('click', function() {
$(this).addClass('active');
$(this).closest('li.treeview').addClass('active');
})
.active>a {
color: green;
}
<script src="https://code.jquery.com/jquery-3.4.1.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
<ul>
<li class="treeview">
<a href="#"><i class="fa fa-link"></i> <span>Multilevel</span>
<span class="pull-right-container">
<i class="fa fa-angle-left pull-right"></i>
</span>
</a>
<ul class="treeview-menu">
<li class="">Link in level 2</li>
<li>Link in level 2</li>
</ul>
</li>
</ul>
If you need the entire treeview ancestry of an active <li> to have the class .active, you can use jQuery's :has:
$('.treeview:has(li.active)').addClass('active');
$('.treeview:has(li.active)').addClass('active');
.active::before {content: 'Active - '}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<li class="treeview">1
<ul>
<li class="treeview">2
<ul>
<li class="treeview">3
<ul>
<li class="active">4</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li class="treeview">1
<ul>
<li class="treeview">2
<ul>
<li class="treeview">3
<ul>
<li>4</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li class="treeview">1
<ul>
<li class="treeview">2
<ul>
<li class="treeview">3
<ul>
<li>4</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
If you need only the immediately closest treeview, you can use .closest():
$('.treeview li.active').closest(".treeview").addClass('active');
$('.treeview li.active').closest(".treeview").addClass('active');
.active::before {content: 'Active - '}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<li class="treeview">1
<ul>
<li class="treeview">2
<ul>
<li class="treeview">3
<ul>
<li class="active">4 (Active)</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li class="treeview">1
<ul>
<li class="treeview">2
<ul>
<li class="treeview">3
<ul>
<li>4</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li class="treeview">1
<ul>
<li class="treeview">2
<ul>
<li class="treeview">3
<ul>
<li>4</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
You don't want to select any li.active outside of the .treeview tree hierarchy:
$('.treeview li.active').closest('.treeview').addClass('active');

Removing items by its contained text from html

I'm looking for a solution to remove items from my html when the page is loaded.
<ul class="nav navbar-nav">
<li class="dropdown">
Модули <span class="caret"></span>
<ul class="dropdown-menu" role="menu">
<li>
<strong>blabla</strong>
</li>
<li>
blabla6
</li>
<li role="presentation" class="divider"></li>
<li>
<strong>blabla5</strong>
</li>
<li>
blabla4
</li>
<li>
blabla3
</li>
<li>
blabla2
</li>
<li>
blabl1
</li>
</ul>
</li>
So I want to remove for example blabla4, blabla2, blabla1 including their <li> tags
This is what I've tried so far
<script type="text/javascript">
// select relevant elements
var elements = $('content-main');
// go through the elements and find the one with the value
elements.each(function(index, domElement) {
var $element = $(domElement);
// does the element have the text we're looking for?
if ($element.text() === "blabla2") {
$element.hide(); // hide the element with jQuery return false;
// jump out of the each
}
});
</script>
Just collect the list items, cast the resulting NodeList to an Array, and iterate over it, removing items whose innerHTML contains 'blabla'.
const listitems = Array.from(document.querySelectorAll('.dropdown-menu li'));
for (const listitem of listitems) {
if (listitem.innerHTML.indexOf('blabla') != -1) {
listitem.parentNode.removeChild(listitem);
}
}
<ul class="dropdown-menu" role="menu">
<li>
<strong>blabla</strong>
</li>
<li>
blabla6
</li>
<li role="presentation" class="divider"></li>
<li>
<strong>blabla5</strong>
</li>
<li>
blabla4
</li>
<li>
blabla3
</li>
<li>
blabla2
</li>
<li>
blabl1
</li>
</ul>
Use JQuery .remove() to delete HTML tags, But you should have a selector on the tags that you want to remove:
$( document ).ready(function() {
$('.dropdown-menu').find("li").slice(4, 5).remove();
$('.dropdown-menu').find("li").slice(5, 6).remove();
$('.dropdown-menu').find("li").slice(5, 6).remove();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="nav navbar-nav">
<li class="dropdown">
Модули <span class="caret"></span>
<ul class="dropdown-menu" role="menu">
<li>
<strong>blabla</strong>
</li>
<li>
blabla6
</li>
<li role="presentation" class="divider"></li>
<li>
<strong>blabla5</strong>
</li>
<li>
blabla4
</li>
<li>
blabla3
</li>
<li>
blabla2
</li>
<li>
blabl1
</li>
</ul>
</li>
</ul>
You can create a array data structure that will hold the values for which <li> should be removed then loop over to all the <li> tags inside the class dropdown-menu and remove them based on their content match with the array value:
$(document).ready(function(){
var removeText = ['blabla4', 'blabla2', 'blabla1'];
$('.dropdown-menu li').each(function(){
var text = $(this).find('a').text().trim();
if(removeText.indexOf(text) !== -1){
$(this).remove();
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="nav navbar-nav">
<li class="dropdown">
Модули <span class="caret"></span>
<ul class="dropdown-menu" role="menu">
<li>
<strong>blabla</strong>
</li>
<li>
blabla6
</li>
<li role="presentation" class="divider"></li>
<li>
<strong>blabla5</strong>
</li>
<li>
blabla4
</li>
<li>
blabla3
</li>
<li>
blabla2
</li>
<li>
blabl1
</li>
</ul>
</li>
You can do it using JQuery:
$(".dropdown-menu > li > a").each(function () {
var $this = $(this);
if ($this.html() == 'bla bla bla') {
$this.parent().remove();
}
});
An alternative is using the selector :contains and the function closest to select the parent element li.
This approach removes the element li with text blabla4
$('#remove').on('click', function() {
$("li a:contains(blabla4)").closest('li').remove();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="nav navbar-nav">
<li class="dropdown">
Модули <span class="caret"></span>
<ul class="dropdown-menu" role="menu">
<li>
<strong>blabla</strong>
</li>
<li>
blabla6
</li>
<li role="presentation" class="divider"></li>
<li>
<strong>blabla5</strong>
</li>
<li>
blabla4
</li>
<li>
blabla3
</li>
<li>
blabla2
</li>
<li>
blabl1
</li>
</ul>
</li>
</ul>
<button id='remove'>remove blabla4</button>
You can select the items using querySelectorAll, convert the NodeList to Array with Array.from, then iterate over each item and remove it.
const wordsToRemove = ['blabla3', 'blabla2'];
const items = Array.from(document.querySelectorAll('li > a'));
const result = items
.filter(item => wordsToRemove.includes(item.textContent))
.forEach(item => item.parentNode.parentNode.removeChild(item.parentNode));
<ul class="nav navbar-nav">
<li class="dropdown">
Модули <span class="caret"></span>
<ul class="dropdown-menu" role="menu">
<li>
<strong>blabla</strong>
</li>
<li>
blabla6
</li>
<li role="presentation" class="divider"></li>
<li>
<strong>blabla5</strong>
</li>
<li>
blabla4
</li>
<li>
blabla3
</li>
<li>
blabla2
</li>
<li>
blabl1
</li>
</ul>
</li>

Show/Hide submenu by click HTML

I have a side menu with some menu items.
One menu items can have some submenu items
Here is how I realize this
<div id="mySidenav" class="sidenav mainmenu">
×
Home
<li>Calendar
<ul class="submenu">
<li>- Shedule new appointment</li>
</ul>
</li>
Patient Database
<li>Findings
<ul class="submenu">
<li>- All Findings</li>
<li>- Open Findings</li>
</ul>
</li>
<li>Controlling
<ul class="submenu">
<li>- Patients</li>
<li>- Medical Partners</li>
<li>- Internal Controlling</li>
</ul>
</li>
<li>Invoices
<ul class="submenu">
<li>- Receipt of payment</li>
</ul>
</li>
I need to click on a menu item and it will show submenu items if I click once again it will hide them. How can I realize this?
See here I apply click even on li not on because on anchor you add a url of other pages, so 22 event not fired on same element.Checkout and if any issue let me know
$(document).ready(function() {
$('.main_wrapper li').on('click', function() {
$(this).children('.submenu').slideToggle();
});
});
.submenu {
display: none;
}
ul li {
background-color: #000;
margin-bottom: 5px;
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="mySidenav" class="sidenav mainmenu">
×
Home
<ul class="main_wrapper">
<li>Calendar
<ul class="submenu">
<li>- Shedule new appointment</li>
</ul>
</li>
<li>Patient Database</li>
<li>Findings
<ul class="submenu">
<li>- All Findings</li>
<li>- Open Findings</li>
</ul>
</li>
<li>Controlling
<ul class="submenu">
<li>- Patients</li>
<li>- Medical Partners</li>
<li>- Internal Controlling</li>
</ul>
</li>
<li>Invoices
<ul class="submenu">
<li>- Receipt of payment</li>
</ul>
</li>
</ul>
if you use bootstrap then it will be easy to do with it.
<div id="mySidenav" class="sidenav mainmenu">
×
Home
<!-- my changes starts here -->
<li data-toggle="collapse" data-target="#test">Calendar
<ul class="submenu collapse" id="test">
<li>- Shedule new appointment</li>
</ul>
</li>
Patient Database
<li>Findings
<ul class="submenu">
<li>- All Findings</li>
<li>- Open Findings</li>
</ul>
</li>
<li>Controlling
<ul class="submenu">
<li>- Patients</li>
<li>- Medical Partners</li>
<li>- Internal Controlling</li>
</ul>
</li>
<li>Invoices
<ul class="submenu">
<li>- Receipt of payment</li>
</ul>
</li>
source: https://www.w3schools.com/bootstrap/bootstrap_collapse.asp

DOM traversal from a span element inside an anchor to list

I can't figure how to travers the DOM, starting from <span class = "open-menu-link">, I want to reach <ul class="sub-menu"> .
The script
<script> $('.open-menu-link').click(function(e){
alert(e.currentTarget);
});
</script>
return a Object HTMLSpanElement, but if I code e.currentTarget.parentNode; it returns http://localhost/mysite/home.php. Doing e.currentTarget.children; I get Object HTMLCollection, but if I try e.currentTarget.children[1] I get undefined... so how can I reach <ul class="sub-menu">?
The snippet is the follow:
<ul class="menu">
<li>Work</li>
<li class="menu-item-has-children">Haschildren <span class = "open-menu-link">+</span>
<ul class="sub-menu">
<li>Child 1</li>
<li>Child 2</li>
<li>Child 3</li>
</ul>
</li>
<li>Careers</li>
<li>Contact</li>
</ul>
$(function() {
$('.open-menu-link').click(function(e){
console.log(e.target.parentNode.nextElementSibling);
console.log(e.target.parentNode.parentNode.children[1]);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="menu">
<li>Work</li>
<li class="menu-item-has-children">
Haschildren <span class="open-menu-link">+</span>
<ul class="sub-menu">
<li>Child 1</li>
<li>Child 2</li>
<li>Child 3</li>
</ul>
</li>
<li>Careers</li>
<li>Contact</li>
</ul>
There are couple of options:
$('.open-menu-link').click(function(e){
console.log(e.target.parentNode.nextElementSibling);
console.log(e.target.parentNode.parentNode.children[1]);
});
The <span class = "open-menu-link"> in your code has only one child i.e text node + this is the reason why e.currentTarget.children[1] is giving you undefined.
Coming to the dom traversal, you should start with node <li class="menu-item-has-children"> . Well that is what I can infer from your question.
You need to use preventDefault() because you'r class is a link. By clicking, it'll redirect you to the link.
$('.open-menu-link').click(function(e) {
console.log($(this).parent().next())
e.preventDefault()
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="menu">
<li>Work
</li>
<li class="menu-item-has-children">
Haschildren <span class = "open-menu-link">+</span>
<ul class="sub-menu">
<li>Child 1
</li>
<li>Child 2
</li>
<li>Child 3
</li>
</ul>
</li>
<li>Careers
</li>
<li>Contact
</li>
</ul>

Categories

Resources