Smooth toggle Javascript function - javascript

Well what I want to do is to toggle a menu when is clicked but it's not smooth and it feels tough, I'm a newbie in JS but I do know CSS and HTML well enough, so is there a way to smooth this toggle function?
menu unclicked:
menu clicked:
const toggleButton = document.getElementsByClassName("nav__toggle-button")[0];
const navbarLinks = document.getElementsByClassName("nav__links")[0];
toggleButton.addEventListener("click", () => {
console.log("clicked");
navbarLinks.classList.toggle("active");
toggleButton.classList.toggle("open");
});

If you want to solve this with CSS you can 'animate' the two divs with the transitions property: https://www.w3schools.com/css/css3_transitions.asp
close state:
div {
opacity: 0;
transition: opacity 1s;
}
open state:
div.active {
opacity: 1;
transition: opacity 1s;
}
Two minors:
don't use BEM classes to trigger an event listener, use instead a proper class (js-click or something..)
a small refactor for your first two lines:
const [toggleButton] = document.querySelectorAll(".nav__toggle-button")
const [navbarLinks] = document.querySelectorAll(".nav__links")

You can apply transition and transform properties to the element through CSS.
For example, if you are using a drop down menu and controlling the slide and the opacity:
transform: translateY(-10px);
transition: opacity 150ms ease-in-out, transform 150ms ease-in-out;
You could check out:
https://developer.mozilla.org/en-US/docs/Web/CSS/transition

All you need is a transition and transform property that you can toggle. Transform CSS property is used for handling dimensions, orientation etc of a DOM element. Adding transition adds an effect where the transform properties if changed, change gradually.
const closeButton = document.getElementById("close")
closeButton.addEventListener("click", () => {
const menu = document.getElementById("nav-links")
menu.classList.toggle("closed-list");
})
ol {
width: 100%;
list-style-type: none;
background: gray;
transition: all 0.4s ease-in-out;
}
.closed-list {
transform: scaleY(0);
transform-origin: top;
}
li {
text-align: center;
padding: 12px 0px;
color: white;
font-weight: 700;
font-size: 18px;
}
#close-container {
text-align: right;
}
<div>
<div id="close-container">
<button id="close">
open/close
</button>
</div>
<ol id="nav-links">
<li>Test 1</li>
<li>Test 2</li>
<li>Test 3</li>
<li>Test 4</li>
</ol>
</div>

Related

ToggleClass overlap

I'm trying to use the same button to open and close a menu, I'm sure this is super simple but I'm new to the world of jQuery. I'm using the Wordpress builder 'Oxygen' if that helps. Here's my code:
The modal is an in-built feature in the website builder so I can't provide much code on that. It's basically set to trigger when element with class "open" is clicked, and close with element class "oxy-modal-close".
jQuery
jQuery("#toggle").click(function () {
jQuery('#plus').toggleClass('rotate');
jQuery('#toggle').toggleClass('open oxy-modal-close');
});
HTML
<div id="toggle" class="open">
<img id="plus" src="http://hausse.co.uk/wp-content/uploads/2021/01/plus.svg"/>
</div>
CSS
#plus {
-moz-transition: transform 1s;
-webkit-transition: transform 1s;
transition: transform 0.3s;
width: 35px;
position: fixed;
top: 20px;
right: 20px;
}
.rotate {
transform: rotate(45deg);
}
Basically on the 2nd click, the class is re-adding the class "open", which is causing the menu to flicker as the two actions are conflicting with each other. Video here - https://gph.is/g/ZnNQddo
I have tried adding a delay to the class "open", but for some reason the delay is only working on the first click - on the second it's changing class instantly. This is the code I'm trying for that.
jQuery("#toggle").click(function () {
jQuery('#plus').toggleClass('rotate');
jQuery('#toggle').toggleClass('oxy-modal-close');
var el = jQuery("#toggle");
window.setTimeout(function() {
el.toggleClass('open');
}, 500);
});
You are referencing the id again within the click - you need to reference $(this)... to toggle the class on the click
Also - you need to start with one of the states - that way it can toggle the class to the other state on each click as per the snippet (the cross icon is on the right of the snippet widow as per styling ) - now when you click it rotates as intended.
$("#toggle").click(function() {
$('#plus').toggleClass('rotate');
$(this).toggleClass('open oxy-modal-close');
});
#plus {
-moz-transition: transform 1s;
-webkit-transition: transform 1s;
transition: transform 0.3s;
width: 35px;
position: fixed;
top: 20px;
right: 20px;
}
.rotate {
transform: rotate(45deg);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="toggle" class="open">
<img id="plus" src="http://hausse.co.uk/wp-content/uploads/2021/01/plus.svg"/>
</div>

JQuery Mobile Listview Swipe Menu

I have a standard JQM page with a ListView with auto generated dividers.
I'd like to be able to add some functionality tat would allow the user to swipe left OR right on an item within the listview and it done either of the following;
1) Reveal a star icon and create some info in localstorage. On swiping a second time change the icon to a 'hollow' star and remove the value in localstorage
2) Reveal a 'hollow' star icon which when clicked on creates a value in locastorage and the icon is replaced with a 'filled' star. Likewise, if the star is pressed a second time, the localstorage value is removed and the icon reverts to a 'hollow' star
Im sure Ive seen info on a similar topic elsewhere but can't seem to find it today. So any pointers, tips, links would be greatly appreciated.
Thanks.
Create span element which will contain star. Add spans before each li element.
<ul data-role="listview" id="list">
<span class="yellowStar"></span>
<li>Item 1</li>
<span class="hollowStar"></span>
<li>Item 2</li>
<span class="hollowStar"></span>
<li>Item 3</li>
<span class="hollowStar"></span>
<li>Item 4</li>
<span class="hollowStar"></span>
<li>Item 5</li>
</ul>
Apply the following CSS for both filled and hollow stars.
.ui-listview>.ui-li-static {
overflow: initial; /* to hide spans underneath */
-webkit-transition: -webkit-transform 300ms ease; /* transition effect */
-moz-transition: -moz-transform 300ms ease;
-o-transition: -o-transform 300ms ease;
transition: transform 300ms ease;
}
ul span {
float: right;
padding: 1.3em 20px;
z-index: -1;
}
ul .yellowStar {
background-image: url(filled.png);
background-repeat: no-repeat;
background-position: center;
}
ul .hollowStar {
background-image: url(hollow.jpg);
background-repeat: no-repeat;
background-position: center;
}
And then attach swipeleft to reveal star.
$(document).on("click", "ul span", function () {
$(this).toggleClass("yellowStar hollowStar");
}).on("swipeleft", "ul li", function (e) {
$(this).off("click");
$(this).css({
transform: "translateX(-40px)"
}).one("transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd", function () {
$(this).one("click swiperight", function () {
$(this).css({
transform: "translateX(0)"
});
});
});
});
Whenever swipe is fired, it also fires click, hence, .off("click") is essential when swipe triggers. However, once the transition ends, click and swiperight listeners are attached to close/hide star.
Demo

Animate easy in and easy out when hover a link

Hi guys i want to make a menu similar to this site: http://tommasoraspo.com/creativepartners/DesignLovers/index.html
But I don't know how i would animate the Bookmark to show up when i hover a link. I thought in using animate.css (slideInDown animation) but then it would only show up when hover over but wouldn't get back when hover out.
Initiate Animation on Hover:
function animationHover(element, animation){
element = $(element);
element.hover(
function() {
element.addClass('animated ' + animation);
},
function(){
//wait for animation to finish before removing classes
window.setTimeout( function(){
element.removeClass('animated ' + animation);
}, 2000);
});
}
The site you point to isn't using an javascript. Rather, they are using css3 transitions to animate the background position of an image that is "off-canvas" when the site is loaded.
Here's a fiddle with the relevant css/html.
You may have to tweak the values to suit your specific design and image.
HTML:
<ul class="nav">
<li>Menu Item 1
</li>
<li>Menu Item 2
</li>
<li>Menu Item 3
</li>
<li>Menu Item 4
</li>
</ul>
CSS:
ul.nav {
list-style: none;
margin: 0;
}
ul.nav li {
float: left;
margin: 0 0 0 30px;
}
ul.nav li.current a, ul.nav li a:hover {
background-position: 50% 0;
}
ul.nav li a {
height: 50px;
line-height: 50px;
display: block;
padding: 50px 20px 0;
position: relative;
background: url(http://lorempixel.com/50/70/abstract/) no-repeat 50% -90px;
-webkit-transition: background-position 0.2s linear;
-moz-transition: background-position 0.2s linear;
transition: background-position 0.2s linear;
}

Jquery Hover Class Fade with Background Image

I have the following Jquery script below that adds a the .hover class on rollover and then removes it on rollout. Currently, the background (whether image or color) fades in and out nicely. However, I don't want the menu text to fade in and out.
I'm aware of the CSS3 fade transitions and the Jquery color plugins but would like to have the option of fading in image backgrounds as well (which is why I'd like to fade in a class rather than just background-color.) Any help would be most appreciated:)Thanks in advance.
Jquery
$(document).ready(function () {
//Set the anchor link opacity to 0 and begin hover function
$("#menu-sample-menu li a").hover(function () {
//Fade to an opacity of 1 at a speed of 200ms
$(this).fadeOut(0).addClass('hover').fadeIn(300);
//On mouse-off
}, function () {
//Fade to an opacity of 0 at a speed of 100ms
$(this).fadeOut(300)
.queue(function () {
$(this).removeClass('hover').fadeIn(0).dequeue()
});
});
});
HTML
<nav id="access">
<ul id="menu-sample-menu" class="menu">
<li id="menu-item-198" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-198">Health Care Professional
</li>
<li id="menu-item-197" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-197">Web Designer
<ul class="sub-menu">
<li id="menu-item-199" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-199">Construction Worker
</li>
</ul>
</li>
</ul>
</nav>
Style
#access li {
position:relative;
float:left;
padding:0;
margin:0;
}
#access ul li:first-child {
padding-left:0;
}
#access a {
display:block;
padding:15px 24px;
color:#f0f0f0;
text-decoration:none;
}
#menu-sample-menu li {
color: black;
text-shadow: 0px 1px 4px #777;
background-color: green;
padding: 0 12px 0 12px;
}
#menu-sample-menu li a.hover {
background-color: orange;
background-image: url(images/over.jpg);
}
You can do this without javascript: http://jsfiddle.net/WjrnB/1/
Simply use:
#menu-sample-menu li a:hover {
background-color: orange;
background-image: url(images/over.jpg);
}
instead of
#menu-sample-menu li a.hover {
background-color: orange;
background-image: url(images/over.jpg);
}
and add:
#menu-sample-menu li a {
-khtml-transition: all 0.5s;
-webkit-transition: all 0.5s;
-moz-transition: all 0.5s;
-o-transition: all 0.5s;
-ms-transition: all 0.5s;
transition: all 0.5s;
}
Xarcell's answer is probably the best simplicity-wise. If you are looking to accomplish this with JavaScript, one option would be using JQuery-UI which has addClass and removeClass functions which incorporate transitions.
Basically, the HTML and CSS is the same as above, but the JS would look as follows:
$(document).ready(function () {
//Set the anchor link opacity to 0 and begin hover function
$("#menu-sample-menu li a").hover(function () {
//Fade 'hover' class in at 300ms
$(this).addClass('hover', 300);
//On mouse-off
}, function () {
//Fade 'hover' class out at 300ms
$(this).removeClass('hover', 300);
});
});
And, of course, you would have to include JQuery-UI (I usually use Cloud Flair's CDNJS):
http://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js
Personally, I would use this method if I was already using JQuery-UI. Otherwise, I would go with Xarcell's solution.

Drop down menu hiding menus

I'm building a drop down menu for a project I'm working on, but I don't get it working entirely as is should. I want it to show the sub-menus when I hover the root-level menus, and then close again after a short delay when the menu or sub-menu is not hovered anymore. Most of it works; the sub-menus are showed when root-level items are hovered and it is hidden when I stop hovering the root-level item. The problem is that the sub-menus are also hidden when I move my cursor from the root-level item to a sub-menu item other than the first and hover that. This is obviously not good, so help would be appreciated.
I created a JSFiddle with the code which shows the issue more clearly.
So, here's my code:
menu.htm
<div id=m_wrapper>
<ul id=menu>
<li onMouseOver="show_sub_menu('0')" onMouseOut="start_timer()">Item 1
<div id=s0 onMouseOver="show_sub_menu('0')" onMouseOut="start_timer()">
<a href=#>Item 1.1</a>
<a href=#>Item 1.2</a>
<a href=#>Item 1.3</a>
</div>
</li>
</ul>
</div>
menu.css
#m_wrapper {
position:relative;
display:table;
}
#menu {
position:relative;
}
#menu li {
width:100px;
position:relative;
float:left;
list-style-type:none;
}
#menu div {
position:absolute;
visibility:hidden;
display:inherit;
width:100%;
z-index:30
}
#menu div a {
position:relative;
display:block;
z-index:35;
}
menu.js
var countdown = 300;
var timer = null;
var menu_item = null;
window.show_sub_menu = function(cath) {
if (menu_item) {
menu_item.style.visibility = 'hidden'; //Make sure to show one menu at a time
}
menu_item = window.document.getElementById("s" + cath);
menu_item.style.visibility = 'visible'; //Show menu
if (timer) {
window.clearTimeout(timer); //Reset timer, so menu is kept open
timer = null;
}
};
window.start_timer = function() {
timer = window.setTimeout(close_sub_menu, countdown);
};
window.close_sub_menu = function() {
menu_item.style.visibility = 'hidden';
};
you don't have to make it that complex.
ofcourse you can do same through javascript, but see how easy, readable and simple it is through jQuery.
See this DEMO
Just use following script
$('#menu li').hover(
function(){
$(this).stop().animate({height: '100px'},1000,function(){});
$(this).find('div').show(600);
}//gets called upon mousehover
,
function(){
$(this).stop().animate({height: '20px'},1000,function(){});
} //gets called upon mouseout
); //hover ends
and also, I don't know why you have written tonns of CSS. Just use these:
#menu
{
list-style:none;
}
#menu li
{
width:100px;
border:1px Solid #CCC;
text-align:Center;
cursor:pointer;
height:20px;
overflow:hidden;
}
#menu li div
{
border:1px Solid #CCC;
}
#s0
{
height:auto;
}
#s0 a
{
display:block;
}
There's plenty you can do through it, like selected dropdown item. selection through arrow key and what not. jQuery makes it simple for you.
first of all You should avoid <div> in <li> tags, because is not semantic.
Quite good is multi level menu build only with html and css styles.
HTML
<div id=m_wrapper>
<ul id=menu>
<li>Item 1
<ul>
<li><a href=#>Item 1.1</a></li>
<li><a href=#>Item 1.2</a></li>
<li><a href=#>Item 1.3</a></li>
</ul>
</li>
<li>Item 2</li>
</ul>
</div>
CSS STYLES
#m_wrapper, #menu, #menu li {
position:relative;
}
#m_wrapper {
display:table;
}
#menu li {
float:left;
width:100px;
list-style-type:none;
}
#menu li ul {
display: none;
}
#menu li:hover ul {
display: block;
margin: 0 10px;
padding: 0;
}
This can quite easily be achieved with HTML and CSS alone. Using CSS transitions we can make the menu fade when we hover off.
Example
I have also put this on JsFiddle
HTML
<nav>
<ul id="menu">
<li>
Home
<ul>
<li>Item1</li>
<li>Item2</li>
<li>Item3</li>
</ul>
</li>
<li>About</li>
<li>Contact</li>
</ul>
</nav>
CSS
#menu li
{
position: relative;
display: inline;
list-style: none;
padding-left: 15px;
}
#menu ul
{
margin: 0;
padding: 0;
list-style: none;
opacity: 0;
position: absolute;
top: 20px;
left: 5px;
// Transitions for our fade effect.
-webkit-transition: opacity 2s ease-in-out;
-moz-transition: opacity 2s ease-in-out;
-ms-transition: opacity 2s ease-in-out;
-o-transition: opacity 2s ease-in-out;
transition: opacity 2s ease-in-out;
}
#menu ul li
{
display: block;
}
#menu li:hover > ul
{
opacity: 1;
// This stops the transition from happening on hover.
-webkit-transition: none;
-moz-transition: none;
-ms-transition: none;
-o-transition: none;
transition: none;
}
A pure CSS drop down menu
http://jsfiddle.net/steelywing/GANeX/8/
.nav {
background-color: #def;
height: 20px;
}
.nav * {
transition: all 0.4s ease 0s;
-moz-transition: all 0.4s ease 0s;
-webkit-transition: all 0.4s ease 0s;
-o-transition: all 0.4s ease 0s;
}
li {
display: inline-block;
height: 20px;
}
.dropdown li {
display: block;
}
.dropdown ul {
visibility: hidden;
opacity: 0;
margin-top: -2px;
}
.dropdown:hover ul {
visibility: visible;
opacity: 1;
}
Remember that.. if You decide to implement the fade version, You should use crosbrowser opacity, like this:
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
filter: alpha(opacity=100);
-moz-opacity: 1;
-khtml-opacity: 1;
opacity: 1;

Categories