i try to add dynamic content to tabs and hide content if tab is empty
html code
<ul id="tabs">
<li>One</li>
<li>Two</li>
<li>Three</li>
<li>Four</li>
</ul>
<div id="content_tabs">
<div id="tab1">content 1</div>
<div id="tab2">content 2</div>
<div id="tab3">content 3</div>
<div id="tab4">content 4</div>
</div>
js code
function resetTabs(){
jQuery("#content_tabs > div").hide(); //Hide all content
jQuery("#tabs a").attr("id",""); //Reset id's
}
var myUrl = window.location.href; //get URL
var myUrlTab = myUrl.substring(myUrl.indexOf("#")); // For mywebsite. com/tabs.html#tab2, myUrlTab = #tab2
var myUrlTabName = myUrlTab.substring(0,4); // For the above example, myUrlTabName = #tab
jQuery(function(){
jQuery("#content_tabs > div").hide(); // Initially hide all content
jQuery("#tabs li:first a").attr("id","current"); // Activate first tab
jQuery("#content_tabs > div:first").fadeIn(); // Show first tab content
jQuery("#tabs a").on("click",function(e) {
e.preventDefault();
if (jQuery(this).attr("id") == "current"){ //detection for current tab
return
}
else{
resetTabs();
jQuery(this).attr("id","current"); // Activate this
jQuery(jQuery(this).attr('name')).fadeIn(); // Show content for current tab
}
});
for (i = 1; i <= $("#tabs li").length; i++) {
if (myUrlTab == myUrlTabName + i) {
resetTabs();
jQuery("a[name='"+myUrlTab+"']").attr("id","current"); // Activate url tab
jQuery(myUrlTab).fadeIn(); // Show url tab content
}
}
});
beauty css
#tabs {
overflow: hidden;
width: 100%;
margin: 0;
padding: 0;
list-style: none;
}
#tabs li {
float: left;
margin: 0 -15px 0 0;
}
#tabs a {
float: left;
position: relative;
padding: 0 40px;
height: 0;
line-height: 30px;
text-transform: uppercase;
text-decoration: none;
color: #fff;
border-right: 30px solid transparent;
border-bottom: 30px solid #3D3D3D;
border-bottom-color: #777\9;
opacity: .3;
filter: alpha(opacity=30);
}
#tabs a:hover,
#tabs a:focus {
border-bottom-color: #2ac7e1;
opacity: 1;
filter: alpha(opacity=100);
}
#tabs a:focus {
outline: 0;
}
#tabs #current {
z-index: 3;
border-bottom-color: #3d3d3d;
opacity: 1;
filter: alpha(opacity=100);
}
here demo
http://jsfiddle.net/uVNFp/95/
appreciate if someone know how I do to hide content if tab is empty
Thanks
http://jsfiddle.net/tdf22/1/
Changes from your original fiddle:
Removed contents of <div id="tab2">.
Added the following.
$("#content_tabs > div:empty").each(function() {
$("#tabs > li").eq($(this).index()).hide();
});
EDIT:
In response to your comment about blank space, I created this fiddle:
http://jsfiddle.net/tdf22/3/
In this one, I:
added the following jQuery custom expression
$.expr[":"].emptyOrWhiteSpace = function(obj){
var $this = $(obj);
return ($.trim($this.html()) === "");
};
and changed this line
$("#content_tabs > div:empty").each(function() {
to this
$("#content_tabs > div:emptyOrWhiteSpace").each(function() {
Gustavo, this is just a quick answer I put together so that you have something working. This can be accomplished in a more professional manner. http://jsfiddle.net/tdf22/8/
I simply added this at the bottom of your javascript:
var tabs = $('#tabs li');
for (var i=0; i<tabs.length; ++i) {
if (tabs[i].style.display !== 'none') {
tabs[i].firstChild.id = 'current';
$('#tab'+(i+1)).show();
return false;
}
}
var El = document.getElementById("El"); //replace
If(El.hasChildNodes()) {
El.style.display = "block";
} else {
El.style.display = "none";
}
Related
I have a sticky sidebar like this:
<ul class = "cars">
<li class=""> BMW </li>
......
<li class=""> Mersedes </li>
</ul>
And table like this:
<div class="element-title" id="car-category-1">BMW</div>
.....
<div class="element-title" id="car-category-2">Mersedes</div>
Now what I am trying to do:
Scrolling through the <div id="car-category-1> should change the class of <li> of BMW to .active
Same for Mersedes, if scroll through <div id="car-category-2> then change <li> with Mersedes to active.
this is jquery for click scroll
$(document).on('click', '.model', function () {
var this_id = $(this).data('id');
var gotom = setInterval(function () {
cars_go_to_navtab(this_id);
clearInterval(gotom);
}, 400);
$('.cars li').removeClass('active');
$(this).parent().addClass('active');
});
function cars_go_to_navtab(id) {
var scrolling_div = $('#car-category-' + id);
$('html, body').animate({
scrollTop: scrolling_div.offset().top - 70
}, 500);
}
There is a great article of CSS-Tricks for a pure CSS solution (not sure that it is suitable to your use-case) which also has a link to another great article that uses Intersection Observer. In short, place something like this in your code:
const observer = new IntersectionObserver(entries =>
{
for (const entry of entries) {
if (entry.isIntersecting) {
// add css style here
}
else {
// remove css style here
}
});
observer.observe(document.querySelector('#your-element-selector'));
Also, please mind support table over different browsers (canIuse to the rescue)
A simple implementation using Jquery. Also, explore the possibilities of Intersection Observer API
$(document).on("scroll", function() {
var scrollPos = $(document).scrollTop();
$('#menu a').each(function() {
var currLink = $(this);
var refElement = $(currLink.attr("href"));
if (refElement.position().top <= scrollPos && refElement.position().top + refElement.height() > scrollPos) {
$('#menu ul li a').removeClass("active");
currLink.addClass("active");
} else {
currLink.removeClass("active");
}
});
});
* {
margin: 0;
padding: 0;
}
.container {
display: flex;
font-family: helvetica, sans-serif;
}
.content {
flex: 1;
padding-left: 200px;
}
.section {
background-color: grey;
height: 100vh;
width: 100%;
overflow: hidden;
padding: 20px;
box-sizing: border-box;
}
#menu {
position: fixed;
top: 0;
background: #444;
width: 200px;
}
#menu a {
padding: 10px;
display: flex;
color: #FFF;
text-decoration: none;
}
h1 {
font-size: 30px;
color: #FFF;
}
.active {
background: #4CAF50;
color: #FFF;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div class="container">
<div id="menu">
<ul>
<li><a class="active" href="#bmw">BMW</a>
</li>
<li>Mercedes</li>
</ul>
</div>
<div class="content">
<div class="section" id="bmw">
<h1>
BMW
</h1>
</div>
<div class="section" id="mercedes">
<h1>
Mercedes
</h1>
</div>
</div>
</div>
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
Using Javascript I am creating a list website (as a side-project).
I use the code:
var myNodelist = document.getElementsByTagName("LI");
and that works, but
localStorage.setItem("myNodelist", document.getElementsByTagName("LI"));
doesn't. it just returns [object HTMLCollection]. Does anyone know why?
// Create a "close" button and append it to each list item
var myNodelist = document.getElementsByTagName("LI");
var i;
for (i = 0; i < myNodelist.length; i++) {
var span = document.createElement("SPAN");
var txt = document.createTextNode("\u00D7");
span.className = "close";
span.appendChild(txt);
myNodelist[i].appendChild(span);
}
// Click on a close button to hide the current list item
var close = document.getElementsByClassName("close");
var i;
for (i = 0; i < close.length; i++) {
close[i].onclick = function() {
var div = this.parentElement;
div.style.display = "none";
}
}
// Add a "checked" symbol when clicking on a list item
var list = document.querySelector('ul');
list.addEventListener('click', function(ev) {
if (ev.target.tagName === 'LI') {
ev.target.classList.toggle('checked');
}
}, false);
// Create a new list item when clicking on the "Add" button
function newElement() {
var li = document.createElement("li");
var inputValue = document.getElementById("myInput").value;
var t = document.createTextNode(inputValue);
li.appendChild(t);
if (inputValue === '') {
alert("You must write something!");
} else {
document.getElementById("myUL").appendChild(li);
}
document.getElementById("myInput").value = "";
var span = document.createElement("SPAN");
var txt = document.createTextNode("\u00D7");
span.className = "close";
span.appendChild(txt);
li.appendChild(span);
for (i = 0; i < close.length; i++) {
close[i].onclick = function() {
var div = this.parentElement;
div.style.display = "none";
}
}
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body {
margin: 0;
min-width: 250px;
}
/* Include the padding and border in an element's total width and height */
* {
box-sizing: border-box;
}
/* Remove margins and padding from the list */
ul {
margin: 0;
padding: 0;
}
/* Style the list items */
ul li {
cursor: pointer;
position: relative;
padding: 12px 8px 12px 40px;
list-style-type: none;
background: #eee;
font-size: 18px;
transition: 0.2s;
/* make the list items unselectable */
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
/* Set all odd list items to a different color (zebra-stripes) */
ul li:nth-child(odd) {
background: #f9f9f9;
}
/* Darker background-color on hover */
ul li:hover {
background: #ddd;
}
/* When clicked on, add a background color and strike out text */
ul li.checked {
background: #888;
color: #fff;
text-decoration: line-through;
}
/* Add a "checked" mark when clicked on */
ul li.checked::before {
content: '';
position: absolute;
border-color: #fff;
border-style: solid;
border-width: 0 2px 2px 0;
top: 10px;
left: 16px;
transform: rotate(45deg);
height: 15px;
width: 7px;
}
/* Style the close button */
.close {
position: absolute;
right: 0;
top: 0;
padding: 12px 16px 12px 16px;
}
.close:hover {
background-color: #168e00;
color: white;
}
/* Style the header */
.header {
background-color: #168e00;
padding: 30px 40px;
color: white;
text-align: center;
}
/* Clear floats after the header */
.header:after {
content: "";
display: table;
clear: both;
}
/* Style the input */
input {
margin: 0;
border: none;
border-radius: 0;
width: 75%;
padding: 10px;
float: left;
font-size: 16px;
}
/* Style the "Add" button */
.addBtn {
padding: 10px;
width: 25%;
background: #d9d9d9;
color: #555;
float: left;
text-align: center;
font-size: 16px;
cursor: pointer;
transition: 0.3s;
border-radius: 0;
}
.addBtn:hover {
background-color: #bbb;
}
</style>
</head>
<body>
<div id="myDIV" class="header">
<h2 style="margin:5px">Groceries:</h2>
<input type="text" id="myInput" placeholder="Title...">
<span onclick="newElement()" class="addBtn">Add</span>
</div>
<ul id="myUL">
</ul>
</body>
</html>
If you write var Lists = document.getElementsByTagName("List"); in your console.log(list) you will see the list of elements that you need right ?
The console.log also shows array the same way ,each element of an array is print to the log without you having to write a for() loop.
However if you want to use the array you have to write the for loop
[object HTMLCollection]
means that there is an array of HTML objects, To work with the data you have to use a for loop or array methods so before storing it in local storage
Try Make an array with the object collection with
var arr = Array.from(htmlCollection);
Then save as is or convert to json string with
var myJsonString = JSON.stringify(arr);
I trust this helps
First: its better if you use id to find the dom element from DOM API.
Second: you need to use .innerText to access the text content of list item.
<ul>
<li id="item">hello</li>
</ul>
localStorage.setItem("myNodelist",document.getElementById("item").innerText);
So I want to make a cool type of drop down menu using jquery, but I dont know how to add anything to the place were I want it.
Basically, there is a button that you press which expands this other div, and then on double click it goes back up. I want the other div to have other div links in it but I don't know how.
Here's my html:
<div id = "one"></div>
<div id = "two"></div>
<div id = "three"></div>
<div id = "four"></div>
<div id = "five"></div>
<div id = "six"></div>
<div id = "one1"></div>
<div id = "two2"></div>
<div id = "three3"></div>
<div id = "four4"></div>
<div id = "five5"></div>
<div id = "six6"></div>
Here's my jquery (ignore the comments and arrows):
$('#one1').click(function(){
$('#one').animate({height: '200px'}, "fast");
$('body').append('<div id = "tester"></div>');
});
$('#two2').click(function(){
$('#two').animate({height: '200px'}, "fast");
});
$('#three3').click(function(){
$('#three').animate({height: '200px'}, "fast");
});
$('#four4').click(function(){
$('#four').animate({height: '200px'}, "fast");
});
$('#five5').click(function(){
$('#five').animate({height: '200px'}, "fast");
});
$('#six6').click(function(){
$('#six').animate({height: '200px'}, "fast");
});
I created a plain navBar which I think it is what you are trying to do.
This may help as a jumpstart to add the animation you want: check JsFiddle here
Html
<nav>
<ul>
<li>Home</li>
<li class="dropdown">About
<ul>
<li>About us</li>
<li>About the company</li>
<li>More</li>
</ul>
</li>
<li>Contact</li>
</ul>
</nav>
CSS
nav > ul {
padding: 0;
margin: 0;
float: left;
}
nav > ul > li {
padding: 0;
margin: 0;
list-style: none;
float: left;
position: relative;
}
nav > ul > li.dropdown > ul {
display: none;
position: absolute;
top: 100%;
width: 200px;
background: #BF0A64;
margin: 0;
padding: 0;
}
nav > ul > li.dropdown > ul > li {
margin: 0;
padding: 0;
list-style: none;
}
nav > ul > li.dropdown > ul > li > a {
display: block;
padding: 10px;
color: #FFF;
text-decoration: none;
}
nav > ul > li.dropdown > ul > li > a:hover {
background: #FFF;
color: #BF0A64;
}
nav > ul > li.dropdown.active a {
background: #BF0A64;
}
nav > ul > li.dropdown.active > ul {
display: block;
}
nav > ul > li > a {
padding: 20px;
color: #FFF;
background: #E80C7A;
text-decoration: none;
display: block;
}
nav > ul > li > a:hover {
background: #BF0A64;
}
nav:after,
div:after {
clear: both;
}
Javascript
(function() {
var dropdowns = document.getElementsByClassName('dropdown');
function init() {
for (var i = 0; i < dropdowns.length; i++) {
var item = dropdowns[i];
item.onclick = showOrHideSubmenu;
}
}
function showOrHideSubmenu() {
// hideAllActives(this);
this.classList.toggle('active');
}
function hideAllActives() {
for (var i = 0; i < dropdowns.length; i++) {
var item = dropdowns[i];
if (hasClass(item, 'active')) {
item.classList.toggle('active');
}
}
}
function hasClass(element, cls) {
return (' ' + element.className + ' ').indexOf(' ' + cls + ' ') > -1;
}
init();
}());
You need something like this :
$('div').click(function(){
$(this).animate({height: '200px'}, "fast");
}).dblclick(function(){
$(this).animate({height: '0px'}, "fast");
});
Example : https://jsfiddle.net/DinoMyte/vxn3ozzb/6/
I have a navigation of lets say 12 items, and when resolution gets smaller items drop in a new line. I need to make that when an item doesn't fit on a navigation anymore it should put a "MORE" dropdown button on the right side of nav. and put that item that doesn't fit in a dropdown.
If you don't understand me there is image below.
But the problem is that navigation items aren't always the same width because navigation items are generated from REST api.
I tryed to make jQuery script for calculating items width and adding them to navigation.
Here is the script I created, I made it in a hurry so it's really bad.
I need to help on how to properly calculate items witdh and navigation width and calculating when to add items to navigation or remove items from navigation.
Here is image if you don't get it: http://img.hr/aagV
/*
* Here we check how many items can we put on the navigation bar
* If item doesn't fit we clone it on the more dropdown button
*/
function removeMany() {
var i = $items.length - 1;
if (itemsWidth > navWidth) {
while (itemsWidth > navWidth) {
$($items[i]).removeClass('first-level-item').addClass('second-level-item');
dropdownItems.push($items[i]);
$($items[i]).removeClass('showed');
$items.pop();
i--;
getItemsWidth();
}
$nav.append($navMore);
dropdownItems.reverse().forEach(function (element, index, array) {
$('ul.second-level').append(element);
});
getItems();
}
}
//If window is resized to bigger resolution we need to put back items on the navbar
function addMany() {
var i = dropdownItems.length - 1;
if (dropdownItems.length != 0) {
do {
$('ul.first-level').append(dropdownItems.reverse()[i]);
$items.push(dropdownItems[i]);
dropdownItems.pop();
i--;
getItemsWidth();
} while (itemsWidth < navWidth);
$navMore.remove();
$items.each(function (i) {
$(this).addClass('first-level-item showed').removeClass('second-level-item');
});
if (!(dropdownItems != 0)) {
return;
} else {
$nav.append($navMore);
}
}
}
body {
margin: 0;
padding: 0;
border: 0; }
ul, li {
margin: 0;
padding: 0;
list-style: none; }
ul.second-level li {
display: block !important; }
ul.second-level li > a {
color: black; }
a {
color: #fff;
text-decoration: none;
text-transform: uppercase; }
.second-level-item a {
color: #333 !important; }
.navigation {
width: 960px;
max-width: 100%;
background: #211;
color: #aaa;
margin: 0 auto; }
.first-level .first-level-item {
display: inline-block;
padding: 10px; }
.first-level .item-more {
display: inline-block; }
.first-level .item-more .second-level-item {
display: inline-block; }
.second-level {
position: absolute;
top: 100%;
right: 0;
width: 200px;
background: #fff;
padding: 10px;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.4); }
.has-second-level {
position: relative; }
.has-second-level .second-level {
display: none; }
.has-second-level:hover {
background: #fff;
color: #000; }
.has-second-level:hover .second-level {
display: block; }
/*# sourceMappingURL=style.css.map */
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>DropDown</title>
<link rel="stylesheet" href="css/reset.css"/>
<link rel="stylesheet" href="css/style.css"/>
</head>
<body>
<nav class="navigation">
<ul class="first-level">
<li class="first-level-item showed">Introduction to Irish Culture</li>
<li class="first-level-item showed">Cellular and Molecular Neurobiology</li>
<li class="first-level-item showed">Guitar foundations</li>
<li class="first-level-item showed">Startup Inovation</li>
<li class="first-level-item showed">Astrophysics</li>
<li class="first-level-item item-more has-second-level">
<span> More </span>
<ul class="second-level">
</ul>
</li>
</ul>
</nav>
<script src="https://code.jquery.com/jquery-2.1.1.js"></script>
</body>
</html>
If you have fixed-width list-items, then it is simple to collect extra list-items and push them into a separate list. Here is a simple example. Explanation is in the code comments.
View the snippet in full-screen and try changing the window width.
Also a Fiddle: http://jsfiddle.net/abhitalks/860LzgLL/
Full Screen: http://jsfiddle.net/abhitalks/860LzgLL/embedded/result/
Snippet:
var elemWidth, fitCount, fixedWidth = 120,
$menu = $("ul#menu"), $collectedSet;
// Assuming that the list-items are of fixed-width.
collect();
$(window).resize(collect);
function collect() {
// Get the container width
elemWidth = $menu.width();
// Calculate how many list-items can be accomodated in that width
fitCount = Math.floor(elemWidth / fixedWidth) - 1;
// Create a new set of list-items more than the fit count
$collectedSet = $menu.children(":gt(" + fitCount + ")");
// Empty the collection submenu and add the cloned collection set
$("#submenu").empty().append($collectedSet.clone());
}
* { box-sizing: border-box; margin: 0; padding: 0; }
div { position: relative; background-color: #ccc; height: 32px; overflow: visible; }
ul#menu, ol { height: 32px; max-width: 80%; overflow: hidden; }
ul#menu > li, ol > li { display: block; float: left; height: 32px; width: 120px; padding: 4px 8px; }
ol { position: absolute; right: 0; top: 0; overflow: visible; }
ol > li { min-width: 120px; }
ol ul { position: absolute; top: 120%; right: 10%; }
ol li ul > li { list-style: none; background-color: #eee; border: 1px solid gray; padding: 4px 8px;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<ul id="menu">
<li>Option One</li><li>Option Two</li><li>Option Three</li>
<li>Option Four</li><li>Option Five</li><li>Option Six</li>
</ul>
<ol><li>Collected<ul id="submenu"></ul></li></ol>
</div>
Update:
This is regarding your query on differing / variable widths of list-items. There would be a minor change.
Also a Fiddle: http://jsfiddle.net/abhitalks/tkbmcupt/1/
Full Screen: http://jsfiddle.net/abhitalks/tkbmcupt/1/embedded/result/
Snippet:
var elemWidth, fitCount, varWidth = 0, ctr, $menu = $("ul#menu"), $collectedSet;
// Get static values here first
ctr = $menu.children().length; // number of children will not change
$menu.children().each(function() {
varWidth += $(this).outerWidth(); // widths will not change, so just a total
});
collect(); // fire first collection on page load
$(window).resize(collect); // fire collection on window resize
function collect() {
elemWidth = $menu.width(); // width of menu
// Calculate fitCount on the total width this time
fitCount = Math.floor((elemWidth / varWidth) * ctr) - 1;
// Reset display and width on all list-items
$menu.children().css({"display": "block", "width": "auto"});
// Make a set of collected list-items based on fitCount
$collectedSet = $menu.children(":gt(" + fitCount + ")");
// Empty the more menu and add the collected items
$("#submenu").empty().append($collectedSet.clone());
// Set display to none and width to 0 on collection,
// because they are not visible anyway.
$collectedSet.css({"display": "none", "width": "0"});
}
* { box-sizing: border-box; margin: 0; padding: 0; }
div { position: relative; background-color: #ccc; height: 32px; overflow: visible; }
ul#menu, ol { height: 32px; max-width: 80%; overflow: hidden; }
ul#menu > li, ol > li { display: block; float: left; height: 32px; white-space: nowrap; padding: 4px 8px; }
ol { position: absolute; right: 0; top: 0; overflow: visible; }
ol > li { min-width: 120px; }
ol ul { position: absolute; top: 120%; right: 10%; }
ol li ul > li { list-style: none; background-color: #eee; border: 1px solid gray; padding: 4px 8px;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<ul id="menu">
<li>Option One</li><li>Option Two</li><li>Option Three</li>
<li>Option Four</li><li>Option Five</li><li>Option Six</li>
</ul>
<ol><li>Collected<ul id="submenu"></ul></li></ol>
</div>
Can and SHOULD be optimised (as it is quite inefficient from what i've tested), but that's up to you.
$(document).ready(function(){
var moreW = $(".more").outerWidth(), //width of your "more" element
totalW = -moreW, //cumulated width of list elements
totalN = $('.nav li').length - 1, //number of elements minus the "more" element
dw = document.documentElement.clientWidth;
$('.nav li').each(function(){
totalW += $(this).outerWidth();
});
function moveToDropdown(){
dw = document.documentElement.clientWidth;
//moves elements into the list
while(totalW > (dw - moreW)){
var temp = $(".nav li:nth-last-child(2)"); //element to be moved
totalW = totalW - temp.outerWidth();
$(".dropdown").append(temp.clone());
temp.remove();
}
//moves elements out of the list
var newList = $('.dropdown li').length; //check if we have elements
if(newList > 0){
var element = $('.dropdown li:last-child'), //element to be moved
elementW = $('.dropdown li:last-child').outerWidth(); //width of element to be moved
if(totalW + elementW < dw - moreW){
while(totalW + elementW < dw - moreW ){
var element = $('.dropdown li:last-child'),
elementW = $('.dropdown li:last-child').outerWidth();
totalW = totalW + elementW;
$(".nav > li:last-child").before(element.clone());
element.remove();
}
}
}
}
moveToDropdown();
$(window).resize(moveToDropdown)
});
.clearfix:after{
display:block;
content:'';
clear:both;
}
body,html{
width:100%;
height:100%;
margin:0;
padding:0;
}
ul{
list-style:none;
width:100%;
padding:0;
margin:0;
}
ul li{
float:left;
padding:5px;
}
.nav > li {
position:relative;
}
.nav ul{
position:absolute;
top:25px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="nav clearfix">
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li class="more">
more
<ul class="dropdown">
<!-- we'll add elements here -->
</ul>
</li>
</ul>
This question is too old, but i want to post my answer too. Maybe this is more cleaner and easier way. I have created a pen: https://codepen.io/sergi95/pen/bmNoML
<div id="mainMenu" class="main-menu">
<ul id="autoNav" class="main-nav">
<li>
home
</li>
<li>
about us
</li>
<li>
portfolio
</li>
<li>
team
</li>
<li>
blog
</li>
<li>
contact
</li>
<li id="autoNavMore" class="auto-nav-more">
more
<ul id="autoNavMoreList" class="auto-nav-more-list">
<li>
policy
</li>
</ul>
</li>
</ul>
const $mainMenu = $("#mainMenu");
const $autoNav = $("#autoNav");
const $autoNavMore = $("#autoNavMore");
const $autoNavMoreList = $("#autoNavMoreList");
autoNavMore = () => {
let childNumber = 2;
if($(window).width() >= 320) {
// GET MENU AND NAV WIDTH
const $menuWidth = $mainMenu.width();
const $autoNavWidth = $autoNav.width();
if($autoNavWidth > $menuWidth) {
// CODE FIRES WHEN WINDOW SIZE GOES DOWN
$autoNav.children(`li:nth-last-child(${childNumber})`).prependTo($autoNavMoreList);
autoNavMore();
} else {
// CODE FIRES WHEN WINDOW SIZE GOES UP
const $autoNavMoreFirst = $autoNavMoreList.children('li:first-child').width();
// CHECK IF ITEM HAS ENOUGH SPACE TO PLACE IN MENU
if(($autoNavWidth + $autoNavMoreFirst) < $menuWidth) {
$autoNavMoreList.children('li:first-child').insertBefore($autoNavMore);
}
}
if($autoNavMoreList.children().length > 0) {
$autoNavMore.show();
childNumber = 2;
} else {
$autoNavMore.hide();
childNumber = 1;
}
}
}
// INIT
autoNavMore();
$(window).resize(autoNavMore);
.main-menu {
max-width: 800px;
}
.main-nav {
display: inline-flex;
padding: 0;
list-style: none;
}
.main-nav li a {
padding: 10px;
text-transform: capitalize;
white-space: nowrap;
font-size: 30px;
font-family: sans-serif;
text-decoration: none;
}
.more-btn {
color: red;
}
.auto-nav-more {
position: relative;
}
.auto-nav-more-list {
position: absolute;
right: 0;
opacity: 0;
visibility: hidden;
transition: 0.2s;
text-align: right;
padding: 0;
list-style: none;
background: grey;
border-radius: 4px;
}
.auto-nav-more:hover .auto-nav-more-list {
opacity: 1;
visibility: visible;
}
The script that Abhitalks made did not work properly for different element sizes. I modified the code a little bit do that it does:
$(function() {
function makeMenuFit() {
//Get data
var menuSize = menu.width();
//Determine how many items that fit
var menuTotalWidth = 0;
var itemThatFit = 0;
for(var i = 0; i < menuItems.length; i++) {
menuTotalWidth += menuItems[i];
if(menuTotalWidth <= menuSize) {
itemThatFit++;
continue;
}
break;
}
menu.children().css({"display": "block", "width": "auto"});
var collectedSet = menu.children(":gt(" + (itemThatFit - 1) + ")");
$("#submenu").empty().append(collectedSet.clone());
collectedSet.css({"display": "none", "width": "0"});
}
var menu = $(".tabletNavigation > ul");
var menuItems = [];
menu.children().each(function() {
menuItems.push($(this).outerWidth());
});
$(window).resize(makeMenuFit);
makeMenuFit();
});
I want to check when i click on the Download Drivers, the other li shold open, and when i click again on Download Drivers, it should close again. No hovers just onclick. I also dont want it to close when i click on some of the li underneath the Download drivers
Here's my HMTL:
<ul class="dropdown">
<li><a id="drivers" onclick="dropdown(this); return false;" class="dir">Download Drivers</a>
<ul id="driversmenu" class="sub">
<li><a>Download Drivers</a></li>
<li><a>Driver Widget</a></li>
<li><a>NVIDIA Software</a></li>
</ul>
</li>
</ul>
Here's the Javascript code:
function dropdown(obj)
{
alert("klik");
var elements = document.getElementsByClassName("sub");
var ids = '';
for (var i = 0; i < elements.length; i++)
{
document.getElementById(elements[i].id).style.display = 'none';
}
if (document.getElementById(obj.id + 'menu').style.display == 'block')
{
alert("al open");
document.getElementById(obj.id + 'menu').style.display = 'hidden';
}
else if (document.getElementById(obj.id + 'menu').style.display = 'hidden')
{
alert("niet open");
document.getElementById(obj.id + 'menu').style.display = 'block';
}
return false;
};
And the css, but i don't know if it is relevant:
ul.dropdown { list-style-type: none; width: 300px;float: left; height: 0px; margin-top: 0px; padding-left: 0px; }
ul.dropdown a { display: block; color: white; text-decoration: none; list-style-type: none; }
ul.dropdown li { float: left; padding: 0 0px; border: 1px dotted #d0d0d0; list-style-type: none;}
ul.dropdown li ul { display: none; position: absolute; z-index: 99; }
ul.dropdown li ul li { clear: both; margin-left: 0px; padding-left: 0px; border: 0; min-width: 150px; }
ul.dropdown li ul li:hover { background-color: #d1d1d1; }
ul.dropdown li ul li:hover a { color: red; }
I only get the the alert from "Klik" and "Niet open",
so this one never calls:
if (document.getElementById(obj.id + 'menu').style.display == 'block')
{
alert("al open");
document.getElementById(obj.id + 'menu').style.display = 'hidden';
}
Does someone know what i am doing wrong?
Thanks in advance
Try
function dropdown(obj)
{
var elements = document.getElementsByClassName("sub");
var ids = '', display = document.getElementById(obj.id+'menu').style.display;
for(var i=0; i < elements.length; i++) {
elements[i].style.display='none';
}
if(!display || display=='none'){
document.getElementById(obj.id+'menu').style.display='block';
}
return false;
};
Demo: Fiddle