Problems calculating absolute div - javascript

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. */
}

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!

How to animate clicked li from its current position to top position and hide all li

I have list of different list items so when i click on specific item from list it should move from its current position to top position using jquery animate and at the same time hide remaining list items using jquery.
$(document).ready(function() {
$(".menu").click(function() {
$("li").animate({
top: '2px'
}, 'slow');
});
});
ul>li {
list-style-type: none;
line-height: 34px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="menu">
<li>Account</li>
<li>Profile</li>
<li>History</li>
</ul>
You can show click element by adding addClass and css to added class and simultaneously you can hide others li by jquery hide(). Hope it helps. I'm just adding the animation to it.
$(document).ready(function() {
$("li").click(function() {
$(this).addClass('top');
$('li').hide();
});
});
ul>li {
list-style-type: none;
line-height: 34px;
}
.top{
display:inline-block !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="menu">
<li>Account</li>
<li>Profile</li>
<li>History</li>
</ul>
Inorder to animate top the element has to be able to take the css property top. So far I made the element to be capable enough to take the property top and I animated it to top while reducing the opacity using transition. These jquery this are done for the sibling li elements of the clicked one.
$(document).ready(function() {
$(".menu li").click(function() {
$(this).siblings('li').animate({
top: '-60px'
}, 'fast');
$(this).siblings('li').css({
'opacity': '0'
});
});
});
ul>li {
list-style-type: none;
line-height: 34px;
position: relative;
top: 10px;
transition: all 2s ease;
}
.menu {
position: absolute;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="menu">
<li>Account</li>
<li>Profile</li>
<li>History</li>
</ul>

Triggering a CSS transition by removing a class with Javascript

I'm having trouble figuring out why my CSS transition isn't firing when I programmatically remove a class from an element.
Essentially, I am trying to create a progressively enhanced, infinitely-scrolling carousel using pure Javascript.
The basic idea is that as the user clicks to scroll either left or right, the first or last element is plucked from the parent ul element, and either prepended or appended to the proper location, depending on the scroll-direction of the user's click.
Here is the relevant code:
HTML:
<div id="scroller">
<ul>
<li>
<a>
<img src="...">
</a>
</li>
..... more li elements
<li>
<a>
<img src="...">
</a>
</li>
</ul>
</div>
CSS:
#scroller {
position: absolute;
left: 0em;
height: 8em;
width: 400em;
}
#scroller ul {
list-style: none;
}
#scroller ul li {
overflow: hidden;
float: left;
height: 8em;
width: 8em;
transition: width 1s ease;
}
#scroller ul li.hide {
width: 0em;
}
#scroller ul li a img {
width: 8em;
}
JS (scroll right click event, for example):
/** Remove the element from the end of the list, add the hide class */
var node = this.list.removeChild(this.items[(this.items.length - 1)]);
/** Add the hide class to the node */
node.className += ' hide';
/** Insert the node at the beginning of the scroller */
this.list.insertBefore(node, this.items[0]);
/** Remove the hide class to trigger the transition animation */
node.className = node.className.replace('hide', '');
Everything is working well, in terms of the items being shifted around the ul correctly, so that is not the problem.
The issue is that the CSS transition is not being applied when the width of the li elements are changed by removing the "hide" class.
I had hoped to create a smooth scrolling effect in browsers than can support the CSS transition.
Thanks in advance for not suggesting that I use a JS library! :)
Use a combo of setTimeout and the transitionend event.
Look here for more info on transitionend:
CSS3 transition events
/** Remove the element from the end of the list, add the hide class */
one = document.getElementById('one');
two = document.getElementById('two');
list = document.getElementById('list');
/** Add the hide class to the node */
two.addEventListener('transitionend', end, false);
setTimeout(function(){
two.className += ' hide';
}, 0)
function end(){
/** Insert the node at the beginning of the scroller */
list.insertBefore(two, one);
/** Remove the hide class to trigger the transition animation */
setTimeout(function(){
two.className = two.className.replace('hide', '');
}, 0)
}
#scroller {
position: absolute;
left: 0em;
height: 8em;
width: 400em;
}
#scroller ul {
list-style: none;
}
#scroller ul li {
overflow: hidden;
float: left;
height: 8em;
width: 8em;
transition: width 1s ease;
}
#scroller ul li.hide {
width: 0em;
}
#scroller ul li a {
width: 8em;
background-color:red;
}
<div id="scroller">
<ul id="list">
<li id="one">
<a>
One
</a>
</li>
<li id="two">
<a>
Two
</a>
</li>
</ul>
</div>

Aligning div right next to the list items

I am trying to create div elements and print items on to them dynamically. I've created a demo to show where I've reached.
The issue with my code is that it doesn't show up right next to the list where I want it. Instead it is displayed at the bottom. Is it possible to show the new div right next to the element that I'm hovering over?
$(".bubble").live({
mouseenter : function() {
$("#bubble").show();
$("#bubble").html($(this).attr('id'));
},
mouseleave : function() {
$("#bubble").empty();
}
});
#bubble{
width:100px;
height:20px;
background-color:#666666;
position:absolute;
display:hidden;
}
<ul>
<li><span class="bubble" id="test1">test1</span></li>
<li><span class="bubble" id="test2">test2</span></li>
<li><span class="bubble" id="test3">test3</span></li>
<li><span class="bubble" id="test4">test4</span></li>
<li><span class="bubble" id="test5">test5</span></li>
</ul>
<div id="bubble"></div>
You need to set the position of #bubble relative to the li which is being moused over. Try this:
$("ul").on('hover', '.bubble', function(e) {
if (e.type == 'mouseenter') {
var $el = $(this);
$("#bubble")
.html($el.attr('id'))
.css({
top: $el.offset().top,
left: $el.offset().left + $el.width()
})
.show();
}
else {
$("#bubble").empty();
}
});
Example fiddle
Note that I have removed the use of live() as it has been deprecated, and used on() with a delegate instead. Also I used the hover event.
What about a pure CSS solution?
HTML:
<ul>
<li>
<span class="bubble" id="test1">test1</span>
<div>test1</div>
</li>
<li>
<span class="bubble" id="test2">test2</span>
<div>test2</div>
</li>
<li>
<span class="bubble" id="test3">test3</span>
<div>test3</div>
</li>
<li>
<span class="bubble" id="test4">test4</span>
<div>test4</div>
</li>
<li>
<span class="bubble" id="test5">test5</span>
<div>test5</div>
</li>
</ul>
CSS:
ul li div {
width: 100px;
height: 10px;
background-color: #666666;
position: absolute;
display: none;
}
ul li:hover div {
display: inline;
}
JSFiddle: http://jsfiddle.net/H2ZMc/
Hope this helps:
JS-Fiddle Demo
I append the #bubble to the li
$(".bubble").live({
mouseenter : function() {
$("#bubble").html($(this).attr('id'));
$(this).append($("#bubble").show());
},
mouseleave : function() {
$("#bubble").empty().hide();
}
});
Try this:
var bubble = $("#bubble");
$(".bubble").live({
mouseenter : function(e) {
$("#bubble").html($(this).attr('id'));
e.target.appendChild(bubble);
},
mouseleave : function() {
$("#bubble").empty();
}
});
What this does is appends the bubble element to the element on which the mouse is over. By applying display: inline to the div you can make it appear beside its sibling instead of below it as it will do if you use this code directly.
Do what Mica said and also remove the position:absolute;
So css should be
#bubble{
width:100px;
height:10px;
background-color:#666666;
display:hidden;
display: inline;
float: left;
}
ul{
display: inline;
float: left;
}
http://jsfiddle.net/y44dR/21/
Why use .on() when the #bubble element already exists.
$(".bubble").hover( function( ) {
var offset = $(this).offset();
$("#bubble").html($(this).attr("id"))
.css({ top: offset.top, left: offset.left + $(this).width() })
.show();
}, function( ) {
$("#bubble").html("").hide();
});
Fiddle here
If you give the <ul> and the <div> the following styles it should work.
display: inline;
float: left;
$(".bubble").live({
mouseenter: function() {
$("#bubble").show();
$("#bubble").html($(this).attr('id'));
var p = $(this).position();
$("#bubble").css({left: p.left + $(this).outerWidth(), top: p.top });
},
mouseleave: function() {
$("#bubble").empty().css({top: '', left: ''});
}
});​

Width of 3rd level of menu

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.

Categories