Width of 3rd level of menu - javascript

I have a slide down menu. In HTML I have:
<menu>
<li id="vysledky">Výsledky
<ul class="menu2">
<li>2008
<ul class="menu3">
<li>21.08. - MMSR SCg</li>
<li>R SCOOechová Potôň SK</li>
<li>SCOOTER Brezová /Visonta/ HU</li>
</ul>
</li>
<li>2010</li>
<li>2011<</li>
</ul>
</li>
<li id="forum"><span>Fórum</span></li>
</menu>
And now i want to automaticly set the width of each 3rd level of menu (menu3) by the longest text in it. So in this example the width of this .menu3 will be the width of text "SCOOTER Brezová /Visonta/ HU".
I can't use css because the width of menu2 is stable and if it will be longer than menu2 its set to width of menu2 (cascade)
So i would use javascript (jquery). I have this code:
var i;
var podm;
$('menu>li').each(function() {
podm = 0;
if($(this).children('ul').size()) {
$(this).each(function() {
if($(this).children('ul').size()) {
$(this).each(function() {
podm++;
i = 60;
$(this).find('li a').each(function() {
var w = $(this).text();
$('#js').text(w);
w = $('#js').width();
if(w > i) {
i = w;
}
});
$(this).find("ul.menu3").css("width");
});
}
});
}
});
But this code works bad :-(.
Web: Here

You set the width of the menu3 ul to 345px which causes longer text to overlap. The Javascript just sets this width again.
<ul class="menu3" style="width: 345px; display: block; opacity: 0.13">
Try to remove the width specification and the jQuery code and check if it works. If you need a specific minimum width for the level 3 menu, you can use the min-width CSS attribute.
EDIT:
Ok, spotted it. The problem is the position: relative attribute in .menu3. The CSS for .menu3 should look like this:
.menu3 {
display: none;
position: absolute; /* This changed */
padding: 0;
margin: 0;
list-style: none;
left: 100px;
top: 0px; /* This changed */
background: #464646 url('3menu-po.png') repeat-y;
display: none;
white-space: nowrap;
}
Note the position: absolute. This takes the submenu out of the document flow and therefore it is not affected by the width set in .menu2.

Related

Trying to do a horizontal slide nav with endless loop

Trying to do a regular horizontal nav with arrow that has a endless loop. Tried figuring it out and some how I can't get it to loop back to "all" div.
tried slick carousel but it has this glitch when the page loads
HTML
<div id="second-navigation">
<div id="slider">
<li>All</li>
<li>slide1</li>
<li>slide2</li>
</div>
</div>
JS
var W = $('#second-navigation').width();
var N = $('#slider li').length;
var C = 0;
$('#slider').width( W*N );
$('#left, #right').click(function(){
var myID = this.id=='right' ? C++ : C-- ;
C= C===-1 ? N-1 : C%N ;
$('#slider').stop().animate({left: -C*W }, 1000 );
});
CSS
#second-navigation{
width:300px;
height:150px;
position:relative;
overflow:hidden;
}
#slider{
position:absolute;
height:150px;
left:0;
width:9999px;
}
#slider li{
float:left;
}
One approach would be to as follows:
When a direction button (ie left or right) is clicked, clone the list item that will be moved out of view by the animation (ie the first <li> for the <ul> when the "left" button is clicked)
attach the cloned <li> to the opposite end of the <ul> list (ie append the cloned first to the end of <ul> when "left" is clicked
animate the margin of the <ul> element to hide the original <li> that was cloned (ie for the "left" case, animate the <ul> left margin to "-150px", which is the width of your <li> items)
On completion of the animation, ensure the <ul> margin is reset, and that the now hidden <li> element has been removed
This can be written in code as shown below. There are a few extra things going on here:
The <ul> needs to be the direct parent of <li> items (a <div> cannot parent <li> items)
Flex box is used to achieve horizontal layout of <li> items, which simplifies CSS styling
Compounded animations need to be prevented (ie the case where button click happens during an existing animation). Below, I'm just ignoring clicks if an animation is underway
$("#left").click(function() {
/* If currently animated, early exit */
if($("#second-navigation ul:animated").length) {
return;
}
/* Clone the element that will be hidden */
var firstClone = $("li:first-child").clone();
$("#second-navigation ul")
.animate({
/* Animate ul container left margin to left */
"marginLeft": "-150px"
}, {
done: function() {
/* Reset ul container left margin */
$(this).css("marginLeft", "0px");
/* Remove element that is now hidden */
$("li:first-child", "#second-navigation ul").remove();
}
})
/* Add cloned element to end of list */
.append(firstClone);
});
$("#right").click(function() {
if($("#second-navigation ul:animated").length) {
return;
}
var lastClone = $("li:last-child").clone();
$("ul")
.css({
"marginLeft": "-150px"
})
.animate({
"marginLeft": "0"
}, {
done: function() {
$("li:last-child", "#second-navigation ul").remove();
}
})
.prepend(lastClone);
});
#second-navigation {
position: relative;
overflow: hidden;
width: 300px;
height: 150px;
}
ul {
display: flex;
width: fit-content;
flex-direction: row;
padding: 0;
margin: 0;
}
li {
position: relative;
height: 150px;
width: 150px;
top: 0;
left: 0;
transition: left ease-in-out 1s;
background: linear-gradient(45deg, black, transparent);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div id="second-navigation">
<ul>
<li>All</li>
<li>slide1</li>
<li>slide2</li>
</ul>
</div>
<button id="left">Move left</button>
<button id="right">Move right</button>
Hope this helps!

hide drop down menu on scroll JS only

Could you please give me tips how to make drop-down menu disappear on scroll up and down?
It is a little bit hard to find it in pure js. Just what path to follow and I will figure out myself.
window.onsrcoll = function(){
var position = 0;
var scPos = (this.pageYOffset || document.documentElement.scrollTop) - (document.documentElement.clientTop || 0);
position += scPos;
if(position > scPos) {
// code here to hide drop-down menu.
}
}
/* on smaller size screens when it becomes drop down menu */
#media(max-width: 880px) {
#navi {
display: none;
}
.navWrapper label[for="mygtukas"] {
background: url(images/open.png);
background-size: 100% 100%;
display: block;
width: 55px;
height: 45px;
cursor: pointer;
position: absolute;
right: 2%;
filter: invert(85%);
transition: all 0.5s;
}
.navWrapper input[type="checkbox"]:checked ~ #navi {
display: block;
user-select: none;
position: absolute;
}
<div class="navWrapper" >
<h1 id="myLogo"><span class="initial">E.</span><span class="name">Erlandas</span> Petronis</h1>
<div class="shadow"></div>
<label for="mygtukas" id="icon"></label>
<input type="checkbox" id="mygtukas">
<ul id="navi">
<li id="li"><a id="link" class="active" href="#home">Home</a></li>
<li id="li"><a id="link" href="#about">About</a></li>
<li id="li"><a id="link" href="#portfolio">Portfolio</a></li>
<li id="li"><a id="link" href="#contact">Contact</a></li>
</ul>
</div>
JS does not work, at least does not make sense or am i off the track here?
As I can see that you want to make the drop-down menu disappear when scrolling down.
One way to do it would be by using Javascript.
What you can do is take the getElementById to change the style top of the navbar to make it disappear when scrolling down.
You can do something like this in javascript :
var position = window.pageYOffset;
window.onsrcoll = function(){
var scPos = window.pageYOffset;
if(position>scPos) {
document.getElementById("navbar").style.top = "0";
} else {
document.getElementById("navbar").style.top = "-50px";
}
position = scPos;
}
For this to work, you'll have to give your navbar a position: fixed; and top: 0;
Hide menu on scroll

How to keep <li> elements fixed top and bottom of <ul> element when scrolling

I have a ul with fixed height, which contian dynamic number of li elements, if too many a scrollbar appaers. You can select a lielement by clicking on it.
What I want is the lielement that is active to be fixed at the top if scrolling aboveit or fixed at the bottom if scrolling below it, so the active li element is always showing, and the other li elements just scrolls past the active one.
I have made a plunker. I am using Angular, and I dont know if this can be solved just using CSS or if I need a directive etc. for this.
Html:
div class="parent">
<div class="child1">
<input ng-model="vm.query" type="text" placeholder="Search" />
<ul >
<li ng-repeat="todo in todos" ng-class="{'active': todo.active}" ng-click="activeTodo($index)">
<a>{{todo.name}}</a>
</li>
</ul>
</div>
CSS:
.parent{
display: flex;
}
.child1{
background-color: #eeeeee;
height: 500px;
overflow:scroll;
}
.active{
background-color: red;
position:fixed;
}
Thanks in advance!
I managed this using some CSS and making a directive.
Made a plunker here.
I made a directive which every li element got. Then with jquery in the directive I get the necessary elements like the div which have the scroll, the current li element etc.
Two booleans for checking if the li is fixed at the top or bottom. And then just check if the current scrollPosition(scrollTop) is higher or lower then the current li element. And it also check so the li element got the active boolean attached too it.
return {
restrict: 'A',
link: function($scope, element, attributes){
var scrollDiv = $('#scrollDiv'),
liElement = element,
liElementTop = parseInt(liElement.offset().top),
scrollDivTop = parseInt(scrollDiv.offset().top),
isFixedTop = false,
isFixedBottom = false;
liElement.width(scrollDiv.width());
scrollDiv.on('scroll', function(){
var scrollTop = scrollDiv.scrollTop();
if (!isFixedBottom && !isFixedTop && scrollTop <= liElementTop - (scrollDivTop+(scrollDiv.height()-liElement.height())) && liElement.hasClass("active")) {
isFixedBottom = true;
liElement.css({'position': 'fixed', 'top': scrollDivTop+(scrollDiv.height()-liElement.height()+1),'list-style-type':'none','z-index':'10'});
} else if (isFixedBottom && !isFixedTop && scrollTop >= liElementTop - (scrollDivTop+(scrollDiv.height()-liElement.height()))) {
isFixedBottom = false;
liElement.css({'position': 'static', 'top': 0});
}
else if (!isFixedTop && !isFixedBottom && scrollTop >= liElementTop - scrollDivTop && liElement.hasClass("active")) {
isFixedTop = true;
liElement.css({'position': 'fixed', 'top': scrollDivTop,'list-style-type':'none','z-index':'10'});
}
else if (isFixedTop && !isFixedBottom && scrollTop <= liElementTop - scrollDivTop) {
isFixedTop = false;
liElement.css({'position': 'static', 'top': 0});
}
})
}
};
The consideration of using pure CSS: One of the best solution is this, because those who perhaps want to make an element remain fixed while it is scrolling up and down!
body {
margin: 10px;
}
ul {
display: block;
width: 210px;
max-height: 120px;
overflow-y: auto;
margin: 0;
padding: 0;
}
li {
padding: 8px 10px;
display: block;
font-size: 13px;
cursor: pointer;
background-color: #ddd;
}
li.fixed {
position: -webkit-sticky;
position: sticky;
bottom: 0;
background-color: #111;
color: #f2f2f2;
}
<ul>
<li>Item1</li>
<li>Item2</li>
<li>Item3</li>
<li>Item4</li>
<li>Item5</li>
<li>Item6</li>
<li>Item7</li>
<li>Item8</li>
<li>Item9</li>
<li>Item10</li>
<li>Item11</li>
<li>Item12</li>
<li>Item13</li>
<li>Item14</li>
<li>Item15</li>
<li>Item16</li>
<li>Item17</li>
<li>Item18</li>
<li>Item19</li>
<li>Item20</li>
<li>Item21</li>
<li>Item22</li>
<li>Item23</li>
<li>Item24</li>
<li>Item25</li>
<li>Item26</li>
<li>Item27</li>
<li>Item28</li>
<li>Item29</li>
<li>Item30</li>
<li>Item31</li>
<li>Item32</li>
<li>Item33</li>
<li>Item34</li>
<li>Item35</li>
<li>Item36</li>
<li>Item37</li>
<li>Item38</li>
<li>Item39</li>
<li>Item40</li>
<li>Item41</li>
<li>Item42</li>
<li>Item43</li>
<li>Item44</li>
<li>Item45</li>
<li>Item46</li>
<li>Item47</li>
<li>Item48</li>
<li>Item49</li>
<li>Item50</li>
<li class="fixed">HEADER</li>
</ul>
If I understood you correctly you like the active div on top.
to solve this in css
use position:relative on parent and position:absolute on the child element with top:0

Change a header's position from fixed to relative on opening (active) mobile drop down menu?

I have a responsive design that when viewed on a device less than 600px wide, uses drop down multi-level navigation. It is nested inside a header that is set to position: fixed. The problem is, that when you drop down the menu the menu overflows downward and does not scroll (because the header is fixed), so the tabs are not visible. Is there a way (using Javascript, jQuery or PHP) to dynamically set it so that when the drop down menu (by way of clicking on the hamburger menu icon in the top right or left), it changes the header's position from fixed to relative?
A good example would be www.dribbble.com. When it's less than 800px wide, the header is sticky (fixed), then when you click on the menu in the top left, it's obvious that the header's position automatically changes to relative.
HTML
<header role="banner" class="secondary">
<em>Menu</em> <span aria-hidden="true"></span>
<nav id="nav" role="navigation">
<ul class="menu set">
<li class="subnav">
Link
<ul class="sub-menu">
<li>Link</li>
<li>Link</li>
<li>Link</li>
</ul>
</li>
</ul>
</nav>
</header>
CSS
header[role="banner"] {
width: 100%;
background: #fff;
display: block;
margin: 0 auto;
padding: 0;
box-shadow: 0 2px 4px rgba(0,0,0,0.25);
z-index: 10000;
}
#media all and (min-width: 500px) {
header[role="banner"] {
position: fixed;
top: 0;
left: 0;
clear: both;
height: auto;
display: block;
}
}
#media all and (max-width: 499px) {
header[role="banner"] {
position: fixed;
}
}
JavaScript
$(document).ready(function() {
$('body').addClass('js');
var $menu = $('#nav'),
$menulink = $('.menu-toggle'),
$menuTrigger = $('.subnav > a');
$menulink.click(function(e) {
e.preventDefault();
$menulink.toggleClass('active');
$menu.toggleClass('active');
});
var add_toggle_links = function() {
if ($('.menu-toggle').is(":visible")){
if ($(".toggle-link").length > 0){
}
else{
$('.subnav > a').before('<span class="toggle-link">Open</span>');
$('.toggle-link').click(function(e) {
var $this = $(this);
$this.toggleClass('active').siblings('ul').toggleClass('active');
});
}
}
else{
$('.toggle-link').empty();
}
}
add_toggle_links();
$(window).bind("resize", add_toggle_links);
});
Well, if you have a custom id or some other kind of attribute for a selector than you can change the position CSS property in multiple ways.
CSS3
#media all and (max-width: 800px) {
header[role="banner"] {
position: relative;
}
}
jQuery
$(document).ready(function() {
$('.menu-toggle').click(function() {
if ($( document ).width() < 499)
$('header[role="banner"]').css('position', 'relative');
else
$('header[role="banner"]').css('position', 'fixed');
});
});
Note: You edited your post. Did you realized that you used position: fixed; in both of your CSS #media rules? Change the second to position: relative;.

Problems calculating absolute div

i have created vertical Menu with fixed width and absolute position ul
.categories ul.sub {
position: absolute;
right: -191px;
top: 0;
background: #fff;
width: 190px;}
but the problem is that i dont want to use fixed width and right. I want to calculate the width and the right of a ul depending of h2 class width inside ul with js. example : how is now: http://prntscr.com/rzcvx , how i need: http://prntscr.com/rzd3t
html example:
<div class="categories">
<ul class="maincats">
<li>
<a class="first"><img/><span>Category Name</span></a>
<ul class="sub first">
<li><h2>H2 Title</h2></li>
<li>Title</li>
<li>Title</li>
<li>Title</li>
<li>Title</li>
</ul>
</li>
</ul></div>
i have nothing tried yet, i only use this js
$(".categories li a").hover(
function () {
$(this).addClass("hover");
$(this).next('ul.sub').show();
},
function () {
$(this).removeClass("hover");
$(this).next('ul.sub').hide();
}
);
$(".categories ul.sub").hover(
function () {
$(this).prev().addClass("hover");
$(this).show();
},
function () {
$(this).prev().removeClass("hover");
$(this).hide();
}
);
$(function () {
var zIndexNumber = 10;
// Put your target element(s) in the selector below!
$(".categories ul.sub").each(function () {
$(this).css('zIndex', zIndexNumber);
});
});
Please help me i have basic js skils :)
You may want to try this:
.categories ul.sub {
position: absolute;
right: -100%; /* Not sure if this works, can't test without your html */
top: 0;
background: #fff;
white-space: nowrap; /* Prevent spaces from wrapping when text's overflowing. */
}

Categories