JavaScript's onmouseover and onmouseout events causing blinking - javascript

I have problem with JavaScript, onmouseover and onmouseout events. When mouse comes to bottom edge of desired element, mouseover and mouseout effects start blinking. Here is example:
function menuHover(field)
{
var img = field.nextElementSibling;
var height = img.height;
var bottom = 0 - Math.floor(height / 2);
bottom += 'px';
img.style.display = 'block';
img.style.bottom = bottom;
}
function menuHoverOut(field)
{
var img = field.nextElementSibling;
img.style.display = 'none';
}
DEMO: https://jsfiddle.net/index23/ety2z0zu/9/
Is there solution for this?

CSS would be the recommendation. But here is the answer for your question https://jsfiddle.net/ety2z0zu/11/. Please remove img.style.bottom = bottom; from your JavaScript
function menuHover(field) {
var img = field.nextElementSibling;
var height = img.height;
var bottom = 0 - Math.floor(height / 2);
bottom += 'px';
img.style.display = 'block';
// console.log(height);
}
function menuHoverOut(field) {
var img = field.nextElementSibling;
img.style.display = 'none';
}
a,
a:link {
color: inherit;
text-decoration: none;
}
body {
background-color: #2a4b8b;
}
header nav {
text-align: center;
position: relative;
}
.main-nav {
margin: 0 auto;
padding-right: 25px;
list-style: none;
display: inline-block;
}
.main-nav li {
float: left;
margin-right: 23px;
display: block;
padding-top: 50px;
-webkit-box-shadow: 0 4px 8px rgba(2, 3, 2, .39);
-moz-box-shadow: 0 4px 8px rgba(2, 3, 2, .39);
box-shadow: 0 4px 8px rgba(2, 3, 2, .39);
position: relative;
}
.main-nav li a {
display: block;
padding-left: 25px;
padding-right: 25px;
padding-bottom: 3px;
border-bottom: 5px solid #6173ad;
border-bottom-right-radius: 5px;
border-bottom-left-radius: 5px;
}
.hover-img {
display: none;
position: absolute;
left: 0px;
width: 100%;
height: auto;
}
<header>
<nav>
<ul class='main-nav'>
<li>
<a href='#' onmouseover='menuHover(this);' onmouseout='menuHoverOut(this);'>LINK</a>
<img alt='' class='hover-img' src='https://dl.dropboxusercontent.com/u/32550463/menu-hover.png' />
</li>
<li>
<a href='#' onmouseover='menuHover(this);' onmouseout='menuHoverOut(this);'>LINK</a>
<img alt='' class='hover-img' src='https://dl.dropboxusercontent.com/u/32550463/menu-hover.png' />
</li>
</ul>
</nav>
</header>

Try to rewrite your code to use css possibilities of mouse tracking.
For mouse - use style :hover
To show image under element - use css directive content with after
Look at this Demo

Why not simply use css?
By using the :hover pseudo class on the parent LI element, you can control the visibility of the image, like so:
.main-nav li img.hover-img {
display: none;
}
.main-nav li:hover img.hover-img {
display: inline;
}
See it in action:
https://jsfiddle.net/vugjp340/1/
And maybe it would be nicer with an opacity transition.

Why are you doing that effect in javascript and not just with css?
Three little changes here:
1. remove padding-top from .main-nav li
2. add padding-top from .main-nav li a
3. add:
.main-nav li:hover img.hover-img {
display:block;
}
Now everything is almost the same except you can click on the "entire" button which has now more height like it is visible. https://jsfiddle.net/ety2z0zu/16/

I think I have found out what is a problem. Problem could be in image that appears on mouse over. When image appear it come over a tag, and browser fire mouse out events, then image hide and browser fire mouse over event and so on in the loop.
Thank you all for helping.

Related

How to put an element in hover state when scrolled down using javascript

I am trying to make a div element which when scrolled down will change properties drastically. Here is the codepen example of how I want it to work.
Instead of hover I want it so that when scrolled down, the page wide div will turn into that little circle div which when clicked will function as a back to the top button. It doesn't matter if more classes are added or anything of that sort. I am very new to js and I tried a few things and also googled about it, I got the scroll code from w3school's how to make a back to top button guide which specifies that when scrolled down by 20px the code would react, but I don't know how to turn the JavaScript to JS when scrolled down along with the transformation of the div.
Thanks in advance
I think you want to implement scroll to top functionality, very common these days in most of the web app.
You need to keep below things and design that feature.
There is one header, that should have a reference ID with hash to scroll back to top
Create a button that will always static position (JS) button, will show up when user scroll the window
Bind click event on the button that scroll back to top
Here is the you can see this implementation and use it.
.html
<h1 class="intro-copy">
Scroll down to use this simple back-to-top button made with modern vanilla javascript.
</h1>
<a class="top-link hide" href="" id="js-top">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 6"><path d="M12 6H0l6-6z"/></svg>
<span class="screen-reader-text">Back to top</span>
</a>
.css
body {
height: 2000px;
position: relative;
}
.intro-copy {
padding: 1em;
margin: 50vh auto;
max-width: 15em;
font-family: Helvetica;
font-weight: lighter;
font-size: 2em;
line-height: 1.2;
text-align: center;
}
.top-link {
transition: all .25s ease-in-out;
position: fixed;
bottom: 0;
right: 0;
display: inline-flex;
cursor: pointer;
align-items: center;
justify-content: center;
margin: 0 3em 3em 0;
border-radius: 50%;
padding: .25em;
width: 80px;
height: 80px;
background-color: #F8F8F8;
&.show {
visibility: visible;
opacity: 1;
}
&.hide {
visibility: hidden;
opacity: 0;
}
svg {
fill: #000;
width: 24px;
height: 12px;
}
&:hover {
background-color: #E8E8E8;
svg {
fill: #000000;
}
}
}
// Text meant only for screen readers.
.screen-reader-text {
position: absolute;
clip-path: inset(50%);
margin: -1px;
border: 0;
padding: 0;
width: 1px;
height: 1px;
overflow: hidden;
word-wrap: normal !important;
clip: rect(1px, 1px, 1px, 1px);
&:focus {
display: block;
top: 5px;
left: 5px;
z-index: 100000; // Above WP toolbar
clip-path: none;
background-color: #eee;
padding: 15px 23px 14px;
width: auto;
height: auto;
text-decoration: none;
line-height: normal;
color: #444;
font-size: 1em;
clip: auto !important;
}
}
JS:
// Set a variable for our button element.
const scrollToTopButton = document.getElementById('js-top');
// Let's set up a function that shows our scroll-to-top button if we scroll beyond the height of the initial window.
const scrollFunc = () => {
// Get the current scroll value
let y = window.scrollY;
// If the scroll value is greater than the window height, let's add a class to the scroll-to-top button to show it!
if (y > 0) {
scrollToTopButton.className = "top-link show";
} else {
scrollToTopButton.className = "top-link hide";
}
};
window.addEventListener("scroll", scrollFunc);
const scrollToTop = () => {
// Let's set a variable for the number of pixels we are from the top of the document.
const c = document.documentElement.scrollTop || document.body.scrollTop;
// If that number is greater than 0, we'll scroll back to 0, or the top of the document.
// We'll also animate that scroll with requestAnimationFrame:
// https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame
if (c > 0) {
window.requestAnimationFrame(scrollToTop);
// ScrollTo takes an x and a y coordinate.
// Increase the '10' value to get a smoother/slower scroll!
window.scrollTo(0, c - c / 10);
}
};
// When the button is clicked, run our ScrolltoTop function above!
scrollToTopButton.onclick = function(e) {
e.preventDefault();
scrollToTop();
}

How can i get 2 classes by id inside the same function

I need to target two div elements and toggle their classes simultanouesly.
I understand that I can get multiple divs "by ID" by using .querySelectorAll
but when I get to .classlist.toggle ("NewClassName"); how can I target two classes??
So here's some code:
#small-div{
background-color:#aaaaaa;
border: 3px solid #aaaaaa;
padding: 0px 0px 0px 0px;
margin: auto 10px auto auto;
border-radius: 10px;
overflow: auto;
}
.tobetoggled{
width: 45%;
float: left;
}
#small-div2{
background-color:#aaaaaa;
border: 3px solid #aaaaaa;
padding: 0px 0px 0px 0px;
margin: auto 10px auto auto;
border-radius: 10px;
overflow: auto;
}
.tobetoggled2{
width: 45%;
float: right;
}
.toggletothis{
width: 100%;
float: left;
position: fixed;
display: block;
z-index: 100;
}
.toggletothis2{
width: 100%;
float: left;
position: fixed;
display: block;
z-index: 100;
}
.whensmalldivistoggled{
display: none;
}/* when small-div is clicked, small-div toggles to class "tobetoggled" while small-div 2 simultaneously toggles to class "whensmalldivistoggled" (the display none class) */
<div id="container">
<div class="tobetoggled" onclick="function()" id="small-div">
</div>
<div class="tobetoggled2" onclick="separatefunction()" id="small-div2">
</div>
</div> <!-- end container -->
<script>
function picClicktwo() {
document.querySelectorAll("small-div, small-div2").classList.toggle("toggletothis, whensmalldivistoggled");
}
</script>
So as you can see one div is on the right, the other is on the left, each set to 45% width. So if I toggle one div to 100% width the browser still respects the other divs space instead of taking the whole 100%.
So I'm thinking if I can get the div on the right ,for example, to not display when the div on the left is toggled, it will be out of the way so the left div can take all 100%
Maybe im going about this the wrong way. Any help is welcome. Thanks.
You can create a single javascript function that sets appropriate classes on each element. Since you have only two elements it is not too complex.
HTML
<div id="container">
<div id="lefty" onclick="toggle('lefty', 'righty')">Lefty</div>
<div id="righty" onclick="toggle('righty', 'lefty')">Righty</div>
</div>
JS
function toggle(target, other)
{
var t = document.getElementById(target);
var o = document.getElementById(other);
if (!t.className || t.className == "inative")
{
t.className = "active";
o.className = "inactive";
}
else
{
t.className = "";
o.className = "";
}
}
CSS
#container {
background-color: lightgreen;
padding: 15px 0;
}
#container div {
color: white;
width: 45%;
display: inline-block;
}
#lefty {
background-color: blue;
}
#righty {
background-color: purple;
}
#container div.active {
width: 90%;
}
#container div.inactive {
display:none;
}
https://jsfiddle.net/dLbu9odf/1/
This could be made more elegant or capable of handling more elements with something like toggle(this) and then some DOM traversal and iteration in javascript, but that's a bit beyond scope. If that were the case I would recommend jQuery.

CSS hover does not affect on other element

CSS :hover works when I use it for it's own element, but when i tried to affect another element, it had no effect.
For example, when I hover this button, the hidden links should appear, but they do not.
.dropdown {
position: relative;
display: inline-block;
border: 1px solid black;
width: 200px;
}
.dropbutton {
width: 100%;
height: 60px;
color: white;
background: #017678;
border: none;
}
.dropcontent a {
color: black;
text-align: center;
line-height: 40px;
text-decoration: none;
height: 40px;
background-color: #DDD;
border-width: 0 0 1px 0;
border-style: solid;
border-color: #9fa0a8;
display: none;
}
a:last-of-type {
border: none;
}
.dropbutton:hover .dropcontent {
display: block;
}
<div class="dropdown">
<button class="dropbutton">SHOW CONTENT</button>
<div class="dropcontent">
c1
c2
c3
</div>
</div>
A space is a descendant combinator. It targets descendants, but the div is not a descendant of the button, it is a sibling.
You need to use the adjacent sibling combinator instead: a plus sign.
You also need to target the links (which are descendants of .dropcontent so you should use a descendant combinator there) since it is those which you have set display: none on and not the div.
.dropbutton:hover + .dropcontent a {
Are you using Javascript to do this?
var button = document.getElementsByClassName('.dropbutton')[0],
menuContent = docuemnt.getElementsByClassName('.dropcontent')[0];
button.onmouseover = function(event) {
menuContent.style.display['block'];
}
button.onmouseout = function(event) {
menuContent.style.display['none'];
}
With a slight change to your CSS: .dropbutton should have display: none, and you should remove the display: none from .dropcontent a
I'd move the display: none; to the .dropcontent itself - as it now pertains to its anchors, that is, links, and as such, neither current answer would work -, then use
.dropbutton:hover + .dropcontent
{
display: block;
}
But you must not add anything between dropbutton and dropcontent afterwards, or it will not work any more.

Create horizontal scroll ionic/angularjs

I was trying to create following scroll navigation with ionic, but somehow navigation is not working and style is not quite right. Could anyone help/guide me on what to use?
This is want I want:
This is what I have so far, horizontal scroll-able list, but above is more like navigation bar, item moves to center when you touch/select it.
When first element is active left side of the list should stay empty. They should scroll like navigation.
So far I have horizontal list but scrolling active one to center is not working.
<ion-scroll direction="x" class="wide-as-needed">
<div ng-repeat="type in types" style='display: inline-block; margin: 5px;' >
{{type|uppercase}}
</div>
</ion-scroll>
directive is simple anchor navigation and trying to navigate to element itself so far not luck, it will navigate to itself but only makes it visible not center of navigation list: https://docs.angularjs.org/api/ng/service/$anchorScroll
Also this angular $anchorScroll is designed to vertical scrolling not horizontal...
TabbedSlideBox can also be used, but this plugin also doesn't have tab scroll to center when active
Update for future reference I will leave it here.
You can try to use this
http://demo.jankuri.com/ngSlimscroll/
but for me creating custom directive from this helped.
function center() {
var currentElement = document.getElementById("active");
currentElement.className = "center-menu";
var nav = document.getElementById("nav");
var navWidth = document.getElementById("nav2").offsetWidth;
var margin = 0;
for(var i =0; i<nav.children.length; i++){
if(currentElement == nav.children[i]){
console.log(nav.children[i]);
break;
}else {
margin += nav.children[i].offsetWidth;
}
}
nav.style.marginLeft = (navWidth/2 - margin - currentElement.offsetWidth);
}
css
nav {
background: #9df0e8;
overflow: hidden;
border-bottom: 8px solid #40b5a2;
border-top: 2px solid #40b5a2;
width: 80%;
margin: 0 auto;
}
nav ul { margin: 0 0 2em;
margin-right:-999em;
white-space:nowrap; }
nav ul li { float: left; }
nav ul li a,
nav ul li span {
display: block;
background: #9df0e8;
color: #345661;
text-decoration: none;
padding: 1em;
cursor: pointer;
-webkit-transition-duration: .3s;
transition-duration: .3s;
}
nav ul li a:hover,
nav ul li span:hover { background: #40b5a2; }
.arrow{
width: 0;
height: 0;
border-style: solid;
border-width: 10px 10px 0 10px;
border-color: #9df0e8 transparent transparent transparent;
display: none;
position: absolute;
left:0;
right:0;
margin-left:auto;
margin-right:auto;
}
.center-menu .arrow{display: block;}

Change color of div when hovering over li

I have a stack of li's. I'm trying to get the background color of a div to change upon mouse on and change back upon mouse off. I was able to figure out how to do it, but it's buggy. The gaps between the li's cause an issue where the jquery isn't triggered correctly when I hover from one li to another.
Here's my code: http://jsfiddle.net/blutuu/k93o28rf/8/
It's quite hacky, so I'm hoping for a better implementation. Thanks for your help.
I'm stacking on top of both answers above. I did a little rearranging of the code and I think I finally got what you are looking for. I tucked the <li> tag inside of the <a> tags, at which point the entire element even when a border is added became clicable.
$(document).ready(function() {
$('li').mouseenter(function() {
var color = $(this).data('color');
$('#mbg').css('background-color', color);
});
$('li').mouseout(function() {
$('#mbg').css('background-color', 'blue');
});
});
.resources {
width: 17%;
height: 100vh;
overflow: hidden;
position: absolute;
z-index: 1;
border-right: solid 1px #C5C5C5;
box-shadow: 2px 0px 2px -1px #DCDCDC;
}
.resources ul {
text-align: right;
padding: 0;
margin: auto 0;
}
.resources ul > li a {
list-style-type: none;
height: 65px;
background: #00ADEF;
border-bottom: solid #0088BC 1px;
vertical-align: middle;
overflow: hidden;
padding: 0;
box-shadow: 0px -1px 5px -2px #222 inset;
box-sizing: border-box;
transition: .5s;
}
.resources ul li a:hover {
border-right: 25px solid #8CC63E;
vertical-align: middle;
overflow: hidden;
/*transition: .5s;*/
}
.resources li a {
line-height: 1em;
text-decoration: none;
color: white;
font-size: 20px;
font-weight: bold;
display: block;
padding: 1.13em;
}
#mbg {
position: absolute;
background-color: blue;
width: 100%;
height: 100vh;
margin-left: 17%;
}
#layoutsTable {
border: solid 1px #f08721;
height: 100vh;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id="mbody">
<div class="resources">
<ul>
<a href="#">
<li data-color="#380606">Policies</a>
</li>
<a href="#">
<li data-color="#191919">LMS</a>
</li>
<a href="#">
<li data-color="#cbcbcb">Tips & Tricks</a>
</li>
<li data-color="#f08721">Forms
</li>
</ul>
</div>
<div id="mbg"></div>
</div>
Demo: http://jsfiddle.net/k93o28rf/6/
Use of bind to pass params directly to the changeColor function.
Define a changeColor function so you don't have to define costly vars everytime.
And simply call .css function on your div id to set background-color.
$(document).ready(function() {
var content = $('#mbg');
var changeColor = function(color) {
content.css('background-color', color);
}
$('li').eq(0).hover(
changeColor.bind(null, '#380606')
);
$('li').eq(1).hover(
changeColor.bind(null, '#191919')
);
$('li').eq(2).hover(
changeColor.bind(null, '#191919')
);
$('li').eq(3).hover(
changeColor.bind(null, '#f08721')
);
$('li').mouseout(
changeColor.bind(null, 'blue')
);
});
demo: http://jsfiddle.net/k93o28rf/3/
by using data tag attributes on each of the li elements, you can just have one mouseenter function and one mouseout function to handle the background color changes as shown below.
<div id="mbody">
<div class="resources">
<ul>
<li data-color="#380606">Policies</li>
<li data-color="#191919">LMS</li>
<li data-color="#cbcbcb">Tips & Tricks</li>
<li data-color="#f08721">Forms</li>
</ul>
</div>
<div id="mbg"></div>
</div>
$(document).ready(function() {
$('li').mouseenter(function() {
var color = $(this).data('color');
$('#mbg').css('background-color', color);
});
$('li').mouseout(function() {
$('#mbg').css('background-color', 'blue');
});
});
UPDATE:
Try using linear-gradient instead of border-right on your a elements:
http://jsfiddle.net/em96edb0/
The problem is the border you've applied to the bottom. Add this to your a element in CSS:
box-sizing:conteny-box;
And that should fix it. Also, to be more efficient, use JQuery's .each function. Something like this:
$('li').each( ///your code );

Categories

Resources