I am trying to find out which exact list item was selected in the navigation menu. With this information, I will remove the class active from the previous menu link and add it to the newly selected one.
<ul class="nav navbar-nav navbar-right">
<li class="active">Home</li>
<li>About</li>
<li>Portfolio</li>
<li>Contact</li>
</ul>
JavaScript:
let menuClick = document.getElementsByClassName(".nav");
menuClick.addEventListener('click', changeActive(), false);
function changeActive(){
//enter code here
}
Using
Vanilla JS - DEMO
var menuItems = document.querySelectorAll(".nav a"); // Get all matching selectors; same as SizzleJS $(selector)
for(var i=0; i < menuItems.length; i++){ // Loop through each element and add click event listener
menuItems[i].addEventListener('click', function(event){ // adding event listener.
event.preventDefault();
for(var i=0; i < menuItems.length; i++){
menuItems[i].parentElement.className = ''; // remove current `active` class from parent element `li`. This is not the best approach for removing classes in Vanilla JavaScript; see this answer http://stackoverflow.com/a/2155786/2151050
}
this.parentElement.className = 'active'; // add `active` to current clicked element.
}, false);
}
I am not going to force you to use jQuery, but you should consider it for doing more, and writing less code. :). Here's the jQuery version
jQuery - DEMO
var menuItems = $(".nav a");
$(".nav a").on('click', function(event) {
event.preventDefault();
menuItems.parent().removeClass('active');
$(this).parent().addClass('active');
});
Get the first element of the nodelist for nav:
let menuClick = document.getElementsByClassName("nav")[0];
Attach an event listener (note: changeActive not changeActive()). This will use event delegation to catch the events that bubble up from the anchors.
menuClick.addEventListener('click', changeActive, false);
Now add some code to your function:
function changeActive(e){
// grab the element that's active
let active = this.querySelector('li.active');
// remove the class
active.classList.remove('active');
// add the active class to the parent of the clicked anchor
e.target.parentNode.classList.add('active');
}
DEMO
There is many way to do that:
You can use onhashchange to detect hash changes
function locationHashChanged() {
if(location.hash === "#pageOne") {
// do something
}
else if(location.hash === "#pageTwo") {
// do something
}
}
window.onhashchange = locationHashChanged;
Or simply can bind click event to menu items
HTML:
<ul class="nav navbar-nav navbar-right">
<li class="active">Home</li>
<li>About</li>
<li>Portfolio</li>
<li>Contact</li>
</ul>
JS:
var navs = document.querySelectorAll('.nav a');
navs.click = function (e) {
document.querySelector('active').className.replace('active','');
var target = e.target;
taret.className += ' active';
};
here is way a way with javascript..Note you will have to loop to add a click handler to all objects in the menu.
here is a snippet
function click(e){
alert(e.target.innerHTML);
}
var el=document.getElementsByClassName('nav navbar-nav navbar-right')
for(var i=0;i<el.length;++i){
function t(i){
el[i].addEventListener('click',click,false)
}
t(i)
}
<ul class="nav navbar-nav navbar-right">
<li class="active">Home</li>
<li>About</li>
<li>Portfolio</li>
<li>Contact</li>
</ul>
Related
I have a function where I have a list of links, where when the list link is clicked, it doesn't open a link until it's clicked again. Can someone please tell me how to get this working?
Here is the HTML:
<ul>
<li class = "submenu"> <a class="nav-link" href = "" > About </a> </li>
<li class = "submenu"> <a class="nav-link" href = "" > Gallery </a> </li>
<li class = "submenu"> <a class="nav-link" href = "" > Contact </a> </li>
</ul>
Here is the function:
(function() {
$('.nav-link').delegate("a", "click", function(e){
e.preventDefault();
});
})();
Here's a method using pure JS:
document.getElementsByClassName('nav-link').forEach(e => {
let wasClicked = false;
e.onclick = () => {
if (wasClicked) return true;
wasClicked = false;
// add a class to it
e.className += ' was-clicked-once';
return false; // reject the click
}
});
The delegate method is deprecated since jquery version: 3.0
Use the jquery on() method. it attaches an event handlers for the selected elements and child elements.
(function() {
$('.nav-link').on("click", function(e){
e.preventDefault();
});
})();
I've got bootstrap4 menu like this:
<ul class="navbar-nav ml-auto">
<li class="nav-item"><a class="nav-link" href="#introduction">INTRODUKTION <span class="sr-only">(current)</span></a></li>
</ul>
Default scroll spy adds active to nav-link (a) I need to change this, becouse my active should be after nav-item (li). Can I do that ?
You can see this here:
Example
When I click, everything goes ok - but on scroll - active is a href.
By default .active class will be added to only anchor tags.
Try something like this for your requirement
$('[data-spy="scroll"]').on('activate.bs.scrollspy', function () {
$(".navbar-nav .active").removeClass("active").parent().addClass("active");
})
Add attribute data-spy="scroll"
on <div class="container"> the parent of section with id="introduction"
like
<div class="container" data-spy="scroll">
I found solution. I need just to add new event (cssClassChanged) - and working !
(function(){
// Your base, I'm in it!
var originalAddClassMethod = jQuery.fn.addClass;
jQuery.fn.addClass = function(){
// Execute the original method.
var result = originalAddClassMethod.apply( this, arguments );
// trigger a custom event
jQuery(this).trigger('cssClassChanged');
// return the original result
return result;
}
})();
and then
$(".nav-link").bind('cssClassChanged' , function(e) {
$(".nav-item").each( function() {
if( $(this).hasClass("active") == true ) {
$(this).removeClass("active");
}
});
$(this).removeClass("active").parent().addClass("active");
});
I have a function that targets the li elements of a div id called mk-featured-kits. All of this works perfectly.
(function() {
var myNode = document.getElementById('mk-featured-kits');
myNode.addEventListener("mouseover", function(e) {
console.log(e);
if (e.target.tagName === 'LI') {
// all happens here
}
})();
I am using Chrome to see the console log and it allows me to use this path for the LI's: e.target.tagName.
Since IE 8 and bellow doesn't read addEventListener event, I am using this (code bellow) to check for the feature. The problem is by using this technique I can't access the LI using: e.target.tagName === 'LI' because the event only sees myNode as a tagName === DIV.
(function() {
var myNode = document.getElementById('mk-featured-kits');
if (myNode.addEventListener) { // all browsers except IE before version 9
myNode.addEventListener ("mouseover", function () {myEvent (myNode)}, false);
} else {
if (myNode.attachEvent) { // IE before version 9
myNode.attachEvent ("onmouseover", function () {myEvent (myNode)});
}
}
function myEvent(myNode) {
console.log(myNode);
if (myNode.target.tagName === 'LI') {
// all happens here
}
})();
How can I access the LI as I did on the first script but using the technique of the second script. Thank you in advance.
This is the html code:
<div class="mk-column">
`<div id="mk-featured-kits">
<ul>
<li id="kit01">Link 01</li>
<li id="kit02">Link 02</li>
<li id="kit03">Link 03</li>
<li id="kit04">Link 04</li>
<li id="kit05">Link 05</li>
<li id="kit06">Link 06</li>
<li id="kit07">Link 07</li>
<li id="kit08">Link 08 </li>
</ul>
</div>`
`
Looking for a solution on how to detect if a li has a child ul or ol i discovered jquerys has() which is pretty awesome apart from I need to detect if only the actual clicked li has a child ol, not any of its siblings. Are there any ways of doing this? The documentation doesnt cover this.
HTML
<ol>
<li><a class="delete-li" href="">Page 1</a></li>
<li><a class="delete-li" href="">Page 2</a></li>
<li><a class="delete-li" href="">Page 3 has ol</a>
<ol>
<li><a class="delete-li" href="">Page 4</a></li>
<li><a class="delete-li" href="">Page 5</a></li>
<li><a class="delete-li" href="">Page 6</a></li>
</ol>
</li>
</ol>
JS
$('.delete-li').live('click', function(event){
event.preventDefault();
item_id = $(this).attr('rel');
clicked = $(this);
////////////////////
//check if has sub pages
if(clicked.has('ol')){
answer = confirm('This will delete all sub pages and content are you sure?');
console.log(answer);
if(answer===true){gogogo=true;
}else{gogogo=false;}
}else{ gogogo=true;}
//if yes run AJAX delete
if(gogogo===true){
alert('LI REMOVED');
}
////////////////
});
Checkout the jsfiddle for the code.
has returns a jQuery object which is always true, as your handler is bound to a elements you can use next method and length property:
if ( clicked.next('ol').length )
Note that live method is deprecated, you can use on method instead.
$(document).on('click', '.delete-li', function (event) {
event.preventDefault();
var gogogo = false, $clicked = $(this), item_id = this.rel;
////////////////////
//check if has sub pages
if ($clicked.next('ol').length) {
gogogo = confirm('This will delete all sub pages and content are you sure?');
// console.log(gogogo);
}
if (gogogo === true) {
alert('LI REMOVED');
}
});
http://jsfiddle.net/jMF42/
You are binding the click handler to the a element. You need to be in reference to the li.
listItem = $(this).parent('li');
//check if has sub pages
if (listItem.find('ol').length) {
...
}
jsfiddle
You are calling function on <a> tag, which doesnt have child. If you want to get deeper you need to refer from his parent <li>.
$('.delete-li').on('click', function (event) {
event.preventDefault();
$this = $(this);
if ($this.parent('li').children('ol').length) {
answer = confirm('This will delete all sub pages and content are you sure?');
alert(answer);
} else {
alert('dont');
}
});
http://jsfiddle.net/NGmz6/
I am working on a web site. The type of menu that I want to create is one where you click on something in the menu, and a submenu pops up. But then you can also hover over any other menu item and another submenu will come up, hiding the first one you clicked. You can click anywhere to close the submenu.
I hope that was clear enough, and would appreciate any help you can give.
Here's my very, very simple, cheap, brief, ugly, lazy, father-disappointing version. It uses jQuery, and it probably doesn't actually look anything like what you wanted. But it accomplishes (I think) the one important thing: "locking" the sub-menu open until either another one is opened, or the user clicks somewhere else on the page.
The HTML looks like this...
<ul>
<li>
<a class="author" href="#">Menu Item 1</a>
<ul class="books">
<li><a class="book" href="#">Sub-Menu Item 1</a></li>
<li><a class="book" href="#">Sub-Menu Item 2</a></li>
</ul>
</li>
<!-- ... -->
</ul>
...and here's the JavaScript:
(function ($) {
var $current,
closeSubMenu = function () {
if ($current) {
$current.slideUp();
}
},
openSubMenu = function (e) {
var $books = $(this).next();
e.preventDefault();
e.stopPropagation();
if (!$current || $current[0] !== $books[0]) {
closeSubMenu();
$current = $books;
$books.slideDown();
}
};
$(document).click(function (e) {
var $target = $(e.target);
if ($target.hasClass('author')) {
openSubMenu.call(e.target, e);
} else if ($target.hasClass('book')) {
e.preventDefault();
} else {
closeSubMenu();
$current = null;
}
});
$('.books').slideUp();
}(jQuery));
If nothing else, it should help give you some ideas for how you do decide to do it.