I am trying to create an onload event where a function compares the current URL to an href and displays content according to the href that is shown. I want to accomplish this by selecting a child from a parent, though I am unsure as to how to get the contents within the href specifically. Here is a bit of the code I have written:
html
<ul id="main-nav">
<li class="nav active">Shipping</li>
<li class="nav">returns</li>
<li class="nav">Custom Orders</li>
<li class="nav">Replacements/ Warranty</li>
<li class="nav">Most Frequently Asked Questions</li>
<li class="nav">RAD Principles</li>
<li class="nav">Environmental Stewardship</li>
<li class="nav">MADE in the USA</li>
</ul>
js
var href = $("#main-nav").children('a');
$("div.faq-container").hide();
if (window.location.href.includes(href)) {
$("div.faq-container").eq("0").show();
} else (window.location.href.includes(href)) {
$("div.faq-container").eq("1").show();
}
the main issue I have is that I want to write the line that has
var href = $("#main-nav").children('a');
so that it grabs the contents within the href alone, and nothing else outside of that, so that it would have either "#shipping", "#returns", etc. as its value.
You took the problem by the wrong end. What you need to know is the location.hash to target the right div to display.
This should be closer:
var hash = window.location.hash
// Hide all .faq-container
$("div.faq-container").hide()
// If there is a hash
if(hash){
$("#"+hash).show()
}
Here's a vanilla JavaScript example which will make the selected section visible.
It uses the hashchange event to detect when the hash has changed.
const sections = [...document.querySelectorAll('.section')];
function showSelected () {
sections.forEach(section => section.classList.remove('show'));
if(location.hash.length) {
const section = document.querySelector(location.hash);
if (section) {
section.classList.add('show');
}
}
}
window.addEventListener('hashchange', showSelected);
.section {
margin: 0.5rem;
padding: 0.5rem;
background-color: #e0e0e0;
width: 10rem;
display: none;
}
.show {
display: block;
}
<ul id="main-nav">
<li class="nav active">Shipping</li>
<li class="nav">returns</li>
<li class="nav">Custom Orders</li>
<li class="nav">Replacements/ Warranty</li>
<li class="nav">Most Frequently Asked Questions</li>
<li class="nav">RAD Principles</li>
<li class="nav">Environmental Stewardship</li>
<li class="nav">MADE in the USA</li>
</ul>
<div id="shipping" class="section">#shipping</div>
<div id="returns" class="section">#returns</div>
<div id="custom" class="section">#custom</div>
<div id="replacements" class="section">#replacements</div>
<div id="mostFAQs" class="section">#mostFAQs</div>
<div id="RAD" class="section">#RAD</div>
<div id="environmental" class="section">#environmental</div>
<div id="USA" class="section">#USA</div>
Related
I have three same items in the DOM. Exactly what I mean is a wobbling line <span class="caret"></span>
<ul>
<li class="nav-item-1">
ITEM 1
<span class="caret"></span>
</li>
</ul>
<ul>
<li class="nav-item-2">
ITEM 2
<span class="caret"></span>
</li>
</ul>
<ul>
<li class="nav-item-3">
ITEM 3
<span class="caret"></span>
</li>
</ul>
Scenario:
I click on the first <span class="caret"></span> gets the class "open", and the rest still has only "caret". I click on the second <span class="caret"></span> gets the class "open", and in the first the class "open" is removed. Is it possible? I wrote something like this:
$(".caret").click(function () {
$(this).data('clicked', true);
if ($('.caret').data('clicked')) {
$(".caret").toggleClass('opened');
}
});
It works, but all "caret" classes get toggleClass('opened') and I just want it to get the one you click on...
You were on the right track by using $(this) but then reverted back to using $('.caret'). Do this:
$(".caret").click(function () {
$(this).toggleClass('opened');
});
Askers request to close all other .caret classes:
$(".caret").click(function () {
$(".caret").removeClass('opened');
$(this).addClass('opened');
});
Your HTML is invalid so it is going to produce wrong HTML Markup in the browser. Not knowing how you actually want it to look, I can not offer a solution on fixing it. Once you get it fixed, The basic code should be
$('.caret').on('click', function () {
$('.caret.opened') // all the open carets
.not(this) // removed the one that was clicked
.removeClass('opened'); // remove the class
$(this)
.toggleClass('opened'); // toggle the one that was clicked
//.addClass('opened'); // if you want it always open
});
if one always has to be opened
$('.caret').on('click', function () {
$('.caret.opened') // all the open carets
.removeClass('opened'); // remove the class
$(this)
.addClass('opened'); // set clicked to open
});
I have a feeling you might have meant this
having a span in a UL is invalid HTML
$(".nav-item a").on("click",function(e) {
e.preventDefault();
$(".caret").removeClass('opened');
$(this).next(".caret").addClass('opened'); // could toggle if needed
});
.caret::after { content: "🡁" }
.opened::after { content: "🠿" }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<li class="nav-item" id="nav-1">ITEM<span class="caret"></span></li>
</ul>
<ul>
<li class="nav-item" id="nav-2">ITEM<span class="caret"></span></li>
</ul>
<ul>
<li class="nav-item" id="nav-3">ITEM<span class="caret"></span></li>
</ul>
jQuery is not needed for this unless you're already using it in other places in your project.
const navItems = [...document.querySelectorAll("[class^=nav-item-")];
navItems.forEach(item => {
item.addEventListener("click", () => {
const opened = document.querySelector(".opened");
if (opened) {
opened.classList.remove("opened");
}
item.parentElement.querySelector(".caret").classList.add("opened");
});
});
/* demo only */
.caret.opened:after {
content: "opened";
}
<ul>
<li class="nav-item-1">
ITEM
</li>
<span class="caret"></span>
</ul>
<ul>
<li class="nav-item-2">
ITEM
</li>
<span class="caret"></span>
</ul>
<ul>
<li class="nav-item-3">
ITEM
</li>
<span class="caret"></span>
</ul>
The HTML needs correction. Something like below is syntactically more correct.
Let's add up CSS to show what caret looks like.
And then, in JavaScript, handle the toggle.
$("ul").click(function (e) {
var caret = $(this).find('.caret');
$('.caret').data('clicked', false);
$('.caret').removeClass('opened');
caret.data('clicked', true);
caret.toggleClass('opened');
});
.caret {
background-color: red;
border: 1px solid blue;
width: 10px;
height: 10px;
display: none;
}
.opened {
display: inline-block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<li class="nav-item-1">
ITEM
<span class="caret"></span>
</li>
</ul>
<ul>
<li class="nav-item-2">
ITEM
<span class="caret"></span>
</li>
</ul>
<ul>
<li class="nav-item-3">
ITEM
<span class="caret"></span>
</li>
</ul>
Please correct your HTML tag
missed anchor closing tag
add .nav class on each li
$(".nav").on('click', function() {
if ($(this).next('.caret').hasClass('clicked opened')) {
$('.caret').removeClass('clicked opened');
} else {
$('.caret').removeClass('clicked opened');
$(this).next('.caret').addClass('clicked opened');
}
});
https://jsfiddle.net/n56b84t9/1/
I make a secondary menu and I like it to be displayed when user hover a specific one of the main menu items....
I tried this code but it didn't work...
.second-menu {display:none}
ul li #2:hover + .second-menu {display:block}
<ul>
<li id="1">first</li>
<li id="2">second</li>
<li id="3">third</li>
<ul>
<div class="second-menu">
<ul>
<li>page1</li>
<li>page2</li>
<li>page3</li>
</ul>
</div>
any suggestions?....
only by css or javascript....
If you wish to use CSS, you will have to put your sub menu inside the element that you want to hover.
For the CSS, C.Raf.T's answer is perfect.
If for some reason you want to use javascript you could do something like this
document.getElementById('2').addEventListener('mouseenter', function ()
{
document.getElementById('subMenu').style.display = "block";
});
document.getElementById('2').addEventListener('mouseleave', function ()
{
document.getElementById('subMenu').style.display = "none";
});
Note: the above code requires you to add a "subMenu" id to the div containing your menu. If you wish to display serval menus with only one hover event, use a class instead.
But honestly, the CSS answer is the best way to go if all you need is nested sub menus.
If the sub menu has to be outside of the parent, you will need the javascript.
.second-menu{
display:none;
}
li:hover >.second-menu{
display:block;
}
<ul>
<li id="1">first</li>
<li id="2">second
<ul class="second-menu">
<li>page1</li>
<li>page2</li>
<li>page3</li>
</ul>
</li>
<li id="3">third</li>
<ul>
Answer using Javascript,
document.getElementById('hover').onmouseover = function(){
document.getElementById('second-menu').style.display = 'block';
}
document.getElementById('hover').onmouseout = function(){
document.getElementById('second-menu').style.display = 'none';
}
.second-menu{
display:none;
}
<ul id="hover">
<li id="1">first</li>
<li id="2">second</li>
<li id="3">third</li>
<ul>
<div class="second-menu" id="second-menu">
<ul>
<li>page1</li>
<li>page2</li>
<li>page3</li>
</ul>
</div>
Here is a fiddle
By using pure CSS you have to ensure that your submenu (.second-menu) is a child-node of your hovered HTML-Element. Because CSS unfortunately doesn't know a parent selector.
By using JS you are more flexible. Means placing the submenu wherever you wish.
* { margin: 0; padding: 0; }
.second-menu {display:none; border: 1px solid blue; width: 100%; position: absolute; left: 0; right: 0; }
ul li#two:hover > .second-menu {display:block}
.relative { position: relative; border: 1px solid black; }
li { display: inline-block; }
<ul class="relative">
<li id="one">first</li>
<li id="two">second
<ul class="second-menu">
<li>page1</li>
<li>page2</li>
<li>page3</li>
</ul>
</li>
<li id="three">third</li>
<ul>
I have a problem with my menu in mobile mode. onClick it fadesOut. I want to keep this setting, however, I want it to do nothing, when one clicks on the dropdown part of the menu.
here is link: http://jsfiddle.net/zLLzrs6b/3/
appreciate your help!
also my html:
<nav id="nav-wrap">
<a class="mobile-btn" href="#nav-wrap" title="Show navigation">Show Menu</a>
<a class="mobile-btn" href="#" title="Hide navigation">Hide Menu</a>
<ul id="nav" class="nav">
<li><a class="smoothscroll mobile" href="#about">about</a></li>
<li><a class="smoothscroll mobile" href="#documents">blog</a></li>
<li class="nav-item">dropdown
<ul class="langop">
<li>otion 1</li>
<li>otion 2</li>
</ul>
</li>
</ul>
</nav>
css:
.langop
{
display:none;
position: relative;
width:auto;
}
.nav-item:hover .langop {
display: block;
}
java:
var toggle_button = $("<a>", {
id: "toggle-btn",
html : "Menu",
title: "Menu",
href : "#" }
);
var nav_wrap = $('nav#nav-wrap')
var nav = $("ul#nav");
nav_wrap.find('a.mobile-btn').remove();
nav_wrap.prepend(toggle_button);
toggle_button.on("click", function(e) {
e.preventDefault();
nav.slideToggle("fast");
});
if (toggle_button.is(':visible')) nav.addClass('mobile');
$(window).resize(function(){
if (toggle_button.is(':visible')) nav.addClass('mobile');
else nav.removeClass('mobile');
});
$('ul#nav li a').on("click", function(){
if (nav.hasClass('mobile')) nav.fadeOut('fast');
});
You have several issues here, but the important ones are:
There is no "nav" variable being set. I think you are confusing the $() selector with this "nav" variable.
There is no "mobile" class on your anchor elements.
You can avoid the if clause by simply specifying the anchor class right in the selector: $(a.mobile) You can see a working version of it here: http://jsfiddle.net/zLLzrs6b/ I've added the "mobile" classes to your anchors and cleaned up the jQuery.
So I'm trying to to make a horizontal menu with CSS and JavaScript that is multi-level. I have a toggle function that shows the div container of the submenu, however, when it displays it pushes the links below the container. How can I make it so when I click the link to show a div container that it appears below the rest of the links. Also I would like to make it where only one link can be selected and I have no clue how to do it. I've never used JavaScript before and I'm fairly new to CSS.
I've removed almost all styling from my code. but here is the functionality.
#togglebox {
display:none;
}
#togglebox li{
display: inline-block;
}
#extrabox {
display:none;
background: #E6ECF2;
text-align: center;
min-width: 100%;
}
#extrabox li{
display: inline-block;
}
#extrabox2 {
display:none;
background: #E6ECF2;
text-align: center;
min-width: 100%;
}
#extrabox2 li{
display: inline-block;
}
function toggle_visibility(id) {
var e = document.getElementById(id);
if(e.style.display == 'block')
e.style.display = 'none';
else
e.style.display = 'block';
}
<ul class="sub-menu" style="display:inline;">
<li id="NSM1">Normal Sub Menu</li></td>
<li id="SMEL">Sub-menu Item with Second Level</li>
<li id="NSM2">Normal Sub Menu</li>
<br />
</ul>
<div id="togglebox">
<li id="NSSL1">[Normal Link]</li>
<li id="SSL2">[Has extra Level]</li>
<div id="extrabox">
<li id="sublinkea">3rd level item1</li> <li id="sublinkeb">3rd level item2</li> <li id="sublinkea">3rd level item3</li>
<li id="sublinkeb">3rd level item4</li>
</div>
<li id="SSL3"><li id="sublinksc">[Has Extra Level]</li>
<div id="extrabox2">
<li id="sublinkea">3rd level item1</li>
<li id="sublinkeb">3rd level item2</li>
<li id="sublinkea">3rd level item3</li>
<li id="sublinkeb">3rd level item4</li>
</div>
<li id="NSSL2">[Normal Link]</li>
</div>
</div>
It looks to me like the trouble is that you have #extrabox as a child of #togglebox, when you really want it to a sibling. As it is, #extrabox will affect the positioning of any block-level elements that come after it (as siblings) under #togglebox. A quick fix looks like:
<div id="togglebox">
<ul>
<li id="NSSL1">
[Normal Link]
</li>
<li id="SSL2">
<a href="#" onclick="toggle_visibility('extrabox');">
[Has extra Level]
</a>
</li>
</ul>
</div>
<div id="extrabox">
<!-- put #extrabox contents here -->
</div>
(I also went ahead and fixed the a tags that were children of ul; ul only takes li tags as children.)
Similarly, you'll want to move #extrabox2 out from under #extrabox so that it doesn't affect the positioning of its siblings there.
I'm not sure what you mean by, "Also I would like to make it where only one link can be selected." Could you clarify that?
Hope that helps!
I have my markup like this:
<div class="wrapper-header">
<div class="container">
<div class="navbar">
<ul class="nav navbar-nav">
<li class="">Show Categories</li>
</ul>
</div>
</div>
<div class="wrapper-categories">
<div class="container">
Content Here
</div>
</div>
The .wrapper-categories is display: none; by default, so it only shows once clicked with:
$(".toggle").on('click', function (event){
event.preventDefault();
$(".wrapper-categories").slideToggle("fast");
$(this).html(function(i,html) {
if (html.indexOf('Browse') != -1 ){
html = html.replace('Show','Hide');
} else {
html = html.replace('Hide','Show');
}
return html;
});
});
Now, I'd like to change that to showing on hover instead of on click, with the .wrapper-categories staying open if someone moves their mouse over and closing if it's not on the link or the content div anymore.
I tried replacing changing it to $(".toggle").hover(function() { and that worked, but it's not staying open. What else must I do?
Your code isn't working the way you desire is because the hover event of .toggle works only for itself. As soon as you try to move the mouse cursor over its contents i.e, under .wrapper-categories, the cursor goes out of the .toggle scope.
Here's a working example of how you need to implement this. You need to slightly change the structure of the menu you want to create using a simple structure of ul and li.
Here's is the FIDDLE.
HTML:
<ul class="nav navbar-nav">
<li class="menu">Show Categories
<ul>
<li>
Content Here
</li>
<li>
Content Here
</li>
<li>
Content Here
</li>
</ul>
</li>
</ul>
JS:
$(".menu").mouseover(function(){
$(this).find('ul').css('visibility', 'visible');
});
$(".menu").mouseout(function(){
$(this).find('ul').css('visibility', 'hidden');
});
CSS:
.menu > ul{
visibility:hidden;
}
.menu > ul > li:hover{
font-weight:bold;
}
Here is the solution for your problem.
https://jsfiddle.net/44wrL4g4/2/
I wrapped all in a menu class.
And I have used mouseleave() instead of mouseout(). See the Jquery documentation for these functions.
See the code for further understanding.