I'm trying to create a mouse in and out effect that shows and disappears DIV's according to the mouse function. I've successfully done this, but the mouseout function flickers on and off when im inside the div instead of staying on.
Heres my sample code:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Kow Your Face</title>
<style>
#face {
background-image: url(face.png);
width: 262px;
height: 262px;
}
#lefteye {
background-image: url(circle.png);
width: 28px;
height: 28px;
position: relative;
top: 69px;
left: 59px;
}
#righteye {
background-image: url(circle.png);
width: 28px;
height: 28px;
position: relative;
top: 41px;
left: 167px;
}
#mouth {
background-image: url(circle.png);
width: 28px;
height: 28px;
position: relative;
top: 84px;
left: 114px;
}
</style>
</head>
<body>
<div id="face">
<div id="lefteye" onMouseOver="getElementById('lefteye').style.visibility='hidden'; getElementById('lefteyedes').style.visibility='visible';" onMouseOut="getElementById('lefteye').style.visibility='visible'; getElementById('lefteyedes').style.visibility='hidden';">
</div>
<div id="righteye" onMouseOver="getElementById('righteye').style.visibility='hidden'; getElementById('righteyedes').style.visibility='visible';" onMouseOut="getElementById('righteye').style.visibility='visible'; getElementById('righteyedes').style.visibility='hidden';">
</div>
<div id="mouth" onMouseOver="getElementById('mouth').style.visibility='hidden'; getElementById('mouthdes').style.visibility='visible';" onMouseOut="getElementById('mouth').style.visibility='visible'; getElementById('mouthdes').style.visibility='hidden';">
</div>
</div>
<div id="lefteyedes" style="visibility: hidden;">
<p>Left Eye</p>
</div>
<div id="righteyedes" style="visibility: hidden;">
<p>Right Eye</p>
</div>
<div id="mouthdes" style="visibility: hidden;">
<p>Mouth</p>
</div>
</body>
</html>
Use document.getElementById instead of just getElementById and you can use this keyword to refer to the current element:
<div id="lefteye" onMouseOver="this.style.visibility='hidden'; document.getElementById('lefteyedes').style.visibility='visible';" onMouseOut="this.style.visibility='visible'; document.getElementById('lefteyedes').style.visibility='hidden';">
</div>
For some reason your onmouseout function is being repeatedly called "onmousemove"...this solution should help you suppress the onmouseout function being repeatedly called. I've rewritten your code a little to help make it easier to enforce changes later (illustrated with one of the onmouseover/onmouseout pairs)...give this a shot:
<script type="text/javascript">
function leftEyeVisibility(vis1, vis2) {
//this function should work for the left eye when the left eye is hidden (lefteyedes is visible) and the mouse is moving over (or not moving at all) the hidden left eye div but has not moused out of it
var dg = document.getElementById("lefteye");
var divStyle = window.getComputedStyle(dg, "");
var mousePosition = function (e) {
var xCoord = e.pageX;
var yCoord = e.pageY;
return xCoord + "," + yCoord;
}
var positionArray = mousePosition.split(","); //split the xy coordinates returned by previous function
if ((positionArray[0] > dg.offsetLeft) && (positionArray[0] < dg.offsetLeft + dg.offsetWidth) && (positionArray[1] > dg.offsetTop) && (positionArray[1] < dg.offsetTop + dg.offsetHeight)) {
var mouseOverlap = 'yes';
} else var mouseOverlap = 'no';
if ((divStyle.visibility === 'hidden') && (mouseOverlap === 'yes')) {
return false;
} else {
document.getElementById("lefteye").style.visibility = vis1;
document.getElementById("lefteyedes").style.visibility = vis2;
}
}
</script>
<div id="lefteye" onmouseover="leftEyeVisibility('hidden', 'visible')" onmouseout="leftEyeVisibility('visible', 'hidden')">
</div>
With jQuery it would be much easier to do this...let me know if it works.
Related
I'm building a little site with full page horizontal and vertical scrolling. Check out a codepen demo here. There is a bug with the demo, the 'left' and 'up' buttons don't work how they're supposed to. The 'right' and 'down' buttons work fine. I just threw that together to show you what I'm talking about (excuse my inline styling).
First off, I need to incorporate touchEvents to make the full page scrolling work on mobile devices. If the user swipes left, right, down, or up, the page should move accordingly. I'm still learning the fundamentals of JS and I have no idea where to start with that.
Secondly, I have a few doubts about whether or not I'm using best practices in my JS. For one thing, I repeat myself a lot. For another, I'm pretty sure there's a simpler method for what I'm trying to do. I'd appreciate it if you could take a look at my code and give me some suggestions. Thanks!
You need to modify these two in CSS:
#center.cslide-up {
top: 100vh;
}
#center.cslide-left {
left: 100vw;
}
First one: When the up button is clicked, it will move 100vh down from top position.
Second one: When the left button is clicked, it will move 100vw right from left position.
As far as for mobile phones, I'd suggest try using:
Hammer.js : https://hammerjs.github.io/
Or Refer this answer: https://stackoverflow.com/a/23230280/2474466
And you can reduce the lines of code by cooking up a function and calling it like this: (Make sure to declare panel2 variable globally)
btnL.addEventListener('click', function() {
swiper("left");
});
btnLBack.addEventListener('click', function() {
swiper("left");
});
function swiper(dir){
panelC.classList.toggle('cslide-'+dir);
if(dir=="up") panel2=panelU;
else if(dir=="right") panel2=panelR;
else if(dir=="left") panel2=panelL;
else if(dir=="down") panel2=panelD;
panel2.classList.toggle('slide-'+dir);
}
The function swiper takes a single argument dir which determines in which direction it has to be moved. And you can concatenate the dir with cslide- to move the center container. And use if/else conditions to determine which panel to move and use the same idea for it as well.
And to make it more simpler and a bit efficient, if you're not making use of any other eventlisteners for the buttons or panels and the only aim is to toggle the class around, you can just use inline onClick="swiper('direction');" attribute on the panels and buttons to trigger it only when needed instead of defining the eventlisteners in the script.
var panel2;
var panelC = document.getElementById('center');
var panelU = document.getElementById('up');
var panelR = document.getElementById('right');
var panelD = document.getElementById('down');
var panelL = document.getElementById('left');
var btnU = document.getElementById('btn-up');
var btnR = document.getElementById('btn-right');
var btnD = document.getElementById('btn-down');
var btnL = document.getElementById('btn-left');
var btnUBack = document.getElementById('btn-up-back');
var btnRBack = document.getElementById('btn-right-back');
var btnDBack = document.getElementById('btn-down-back');
var btnLBack = document.getElementById('btn-left-back');
btnU.addEventListener('click', function() {
swiper("up");
});
btnUBack.addEventListener('click', function() {
swiper("up");
});
btnR.addEventListener('click', function() {
swiper("right");
});
btnRBack.addEventListener('click', function() {
swiper("right");
});
btnD.addEventListener('click', function() {
swiper("down");
});
btnDBack.addEventListener('click', function() {
swiper("down");
});
btnL.addEventListener('click', function() {
swiper("left");
});
btnLBack.addEventListener('click', function() {
swiper("left");
});
function swiper(dir){
panelC.classList.toggle('cslide-'+dir);
if(dir=="up") panel2=panelU;
else if(dir=="right") panel2=panelR;
else if(dir=="left") panel2=panelL;
else if(dir=="down") panel2=panelD;
panel2.classList.toggle('slide-'+dir);
}
* {
margin: 0;
padding: 0;
transition: 1.5s ease;
-webkit-transition: 1.5s ease;
overflow: hidden;
background: white;
}
.panel {
width: 100vw;
height: 100vh;
display: block;
position: absolute;
border: 1px solid blue;
}
.btn {
position: absolute;
padding: 16px;
cursor: pointer;
}
#center {
top: 0px;
left: 0px;
right: 0px;
bottom: 0px;
}
#center.cslide-up {
top: 100vh;
}
#center.cslide-left {
left: 100vw;
}
#center.cslide-right {
left: -100vw;
}
#center.cslide-down {
top: -100vh;
}
#up {
top: -100vh;
}
#up.slide-up {
top: 0;
}
#right {
right: -100vw;
}
#right.slide-right {
right: 0;
}
#down {
bottom: -100vh;
}
#down.slide-down {
bottom: 0;
}
#left {
left: -100vw
}
#left.slide-left {
left: 0;
}
<div class="panel" id="center">
<div class="btn" id="btn-up" style="text-align: center; width: 100%;">
up
</div>
<div class="btn" id="btn-right" style="right: 0; top: 50%;">
right
</div>
<div class="btn" id="btn-down" style="text-align: center; bottom: 0; width: 100%;">
down
</div>
<div class="btn" id="btn-left" style="top: 50%;">
left
</div>
</div>
<div class="panel" id="up">
<div class="btn" id="btn-up-back" style="bottom: 0; width: 100%; text-align: center;">
back
</div>
</div>
<div class="panel" id="right">
<div class="btn" id="btn-right-back" style="left: 0; top: 50%;">
back
</div>
</div>
<div class="panel" id="down">
<div class="btn" id="btn-down-back" style="top: 0; width: 100%; text-align: center;">
back
</div>
</div>
<div class="panel" id="left">
<div class="btn" id="btn-left-back" style="right: 0; top: 50%;">
back
</div>
</div>
So I have a set of elements called .project-slide, one after the other. Some of these will have the .colour-change class, IF they do have this class they will change the background colour of the .background element when they come into view. This is what I've got so far: https://codepen.io/neal_fletcher/pen/eGmmvJ
But I'm looking to achieve something like this: http://studio.institute/clients/nike/
Scroll through the page to see the background change. So in my case what I'd want is that when a .colour-change was coming into view it would slowly animate the opacity in of the .background element, then slowly animate the opacity out as I scroll past it (animating on scroll that is).
Any suggestions on how I could achieve that would be greatly appreciated!
HTML:
<div class="project-slide fullscreen">
SLIDE ONE
</div>
<div class="project-slide fullscreen">
SLIDE TWO
</div>
<div class="project-slide fullscreen colour-change" data-bg="#EA8D02">
SLIDE THREE
</div>
<div class="project-slide fullscreen">
SLIDE TWO
</div>
<div class="project-slide fullscreen colour-change" data-bg="#cccccc">
SLIDE THREE
</div>
</div>
jQuery:
$(window).on('scroll', function () {
$('.project-slide').each(function() {
if ($(window).scrollTop() >= $(this).offset().top - ($(window).height() / 2)) {
if($(this).hasClass('colour-change')) {
var bgCol = $(this).attr('data-bg');
$('.background').css('background-color', bgCol);
} else {
}
} else {
}
});
});
Set some data-gb-color with RGB values like 255,0,0…
Calculate the currently tracked element in-viewport-height.
than get the 0..1 value of the inViewport element height and use it as the Alpha channel for the RGB color:
/**
* inViewport jQuery plugin by Roko C.B.
* http://stackoverflow.com/a/26831113/383904
* Returns a callback function with an argument holding
* the current amount of px an element is visible in viewport
* (The min returned value is 0 (element outside of viewport)
*/
;
(function($, win) {
$.fn.inViewport = function(cb) {
return this.each(function(i, el) {
function visPx() {
var elH = $(el).outerHeight(),
H = $(win).height(),
r = el.getBoundingClientRect(),
t = r.top,
b = r.bottom;
return cb.call(el, Math.max(0, t > 0 ? Math.min(elH, H - t) : (b < H ? b : H)), H);
}
visPx();
$(win).on("resize scroll", visPx);
});
};
}(jQuery, window));
// OK. Let's do it
var $wrap = $(".background");
$("[data-bg-color]").inViewport(function(px, winH) {
var opacity = (px - winH) / winH + 1;
if (opacity <= 0) return; // Ignore if value is 0
$wrap.css({background: "rgba(" + this.dataset.bgColor + ", " + opacity + ")"});
});
/*QuickReset*/*{margin:0;box-sizing:border-box;}html,body{height:100%;font:14px/1.4 sans-serif;}
.project-slide {
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.project-slide h2 {
font-weight: 100;
font-size: 10vw;
}
<div class="project-slides-wrap background">
<div class="project-slide">
<h2>when in trouble...</h2>
</div>
<div class="project-slide" data-bg-color="0,200,255">
<h2>real trouble...</h2>
</div>
<div class="project-slide">
<h2>ask...</h2>
</div>
<div class="project-slide" data-bg-color="244,128,36">
<h2>stack<b>overflow</b></h2>
</div>
</div>
<script src="//code.jquery.com/jquery-3.1.0.js"></script>
Looks like that effect is using two fixed divs so if you need something simple like that you can do it like this:
But if you need something more complicated use #Roko's answer.
var fixed = $(".fixed");
var fixed2 = $(".fixed2");
$( window ).scroll(function() {
var top = $( window ).scrollTop();
var opacity = (top)/300;
if( opacity > 1 )
opacity = 1;
fixed.css("opacity",opacity);
if( fixed.css('opacity') == 1 ) {
top = 0;
opacity = (top += $( window ).scrollTop()-400)/300;
if( opacity > 1 )
opacity = 1;
fixed2.css("opacity",opacity);
}
});
.fixed{
display: block;
width: 100%;
height: 200px;
background: blue;
position: fixed;
top: 0px;
left: 0px;
color: #FFF;
padding: 0px;
margin: 0px;
opacity: 0;
}
.fixed2{
display: block;
width: 100%;
height: 200px;
background: red;
position: fixed;
top: 0px;
left: 0px;
color: #FFF;
padding: 0px;
margin: 0px;
opacity: 0;
}
.container{
display: inline-block;
width: 100%;
height: 2000px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
Scroll me!!
</div>
<div class="fixed">
</div>
<div class="fixed2">
</div>
I want to calculate the scrolled distance of a div element within another div element. I am using offsetTop for that, but it always returns 0 in my code. I am unable to figure out where I am making the mistake.
function getScrollVal() {
console.log(window.pageYOffset);
var wrap = document.getElementById("wrapper");
console.log(wrap.id);
console.log(wrap.offsetParent.id);
var parent = wrap.offsetParent;
console.log("scrollTop: " + wrap.scrollTop + " scrollLeft: " + wrap.scrollLeft);
console.log("offsetTop: " + wrap.offsetTop + " offsetLeft: " + wrap.offsetLeft);
/*
var xx = wrap.offsetLeft;
var yy = wrap.offsetTop;
while(wrap = wrap.offsetParent){
xx += wrap.offsetLeft;
yy += wrap.offsetTop;
}
*/
}
body, html {
margin: 0;
padding: 0;
}
#contain {
position: relative;
width:100%;
height: 100vh;
background: yellow;
overflow: auto;
}
#wrapper {
width: 85%;
margin: 0 auto;
background: red;
}
.full {
height: 100vh;
width: 85%;
margin: 0 auto;
}
#one { background:#222;}
#two{ background:#00c590;}
#three{ background:#3429c5;}
#four{background:#bbb;}
#b {
position: fixed;
z-index: 1000;
top: 30px;
left: 30px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
</head>
<body>
<div id="contain">
<div id="wrapper">
<div id="one" class="full"></div>
<div id="two" class="full"></div>
<div id="three" class="full"></div>
<div id="four" class="full"></div>
</div>
</div>
<button id="b" type="button" onClick="getScrollVal();" value="click me">Press me</button>
</body>
</html>
I have tried the js code inside the comment. That one is not providing a fruitful result. Thanks in advance.
Since the element #contain is the overflow element, you can try get the scrollTop like this:
console.log("scroll top:", document.getElementById('contain').scrollTop);
From MDN:
An element's scrollTop is a measurement of the distance of an element's top to its topmost visible content. Element.scrollTop
To be more clear When you run the code ---- click 'show' in the page a div opens up with a gray background and another inner div with green background---onclick on gray background the div needs to close if we click on green div it should not close please help me out Thanks In advance.
I have a text 'show' onclick on show it open's up a div which is set to display=none and this div is set to overflow=hidden. Inside the div I have a another div with matter. This works fine but the issue is onclick of the main div which is set to display=none has to close when it is click in its area.
code:
<html>
<head></head>
<script language="javascript">
function toggle(tId) {
var ele = document.getElementById(tId);
ele.style.display = "block";
}
function cancelToggle(id,e)
{ var target = (e && e.target) || (event && event.srcElement);
var obj = document.getElementById('toggleText');
if(target!=obj){obj.style.display='none'}
}
</script>
<body>
<a id="displayText" href="javascript:toggle('toggleText');">show</a>
<div id="toggleText" style="display: none; background: none repeat scroll 0 0 rgba(0, 0, 0, 0.6);
bottom: 0; height: 100%; left: 0; overflow: hidden; position: fixed; right:100; top: 10; width: 100%;">
<div style="background: none repeat scroll 0 0 #80C5A9; display: block; height: 40%;
position:fixed; bottom: 0; overflow: hidden; width: 100%;">
<h1>Welcome Naren</h1>
<label>Its good for u.All the best</label>
</div>
</div>
</body>
</html>
Does this work?
<html>
<head></head>
<script language="javascript">
function toggle(el) {
if ( el.id && el.style.display == 'block' ) {
el.style.display = 'none';
} else {
el.style.display = 'block';
}
}
function cancelToggle(id,e)
{ var target = (e && e.target) || (event && event.srcElement);
var obj = document.getElementById('toggleText');
if(target!=obj){obj.style.display='none'}
}
function stop() {
if (event.stopPropagation) {
event.stopPropagation();
} else {
window.event.cancelBubble = true;
}
}
</script>
<body>
<a id="displayText" href="javascript:toggle(document.getElementById('toggleText'));">show</a>
<div onClick='toggle(this)' id="toggleText" style="display: none; background: none repeat scroll 0 0 rgba(0, 0, 0, 0.6);
bottom: 0; height: 100%; left: 0; overflow: hidden; position: fixed; right:100; top: 10; width: 100%;">
<div onClick='stop()' style="background: none repeat scroll 0 0 #80C5A9; display: block; height: 40%; position:fixed; bottom: 0; overflow: hidden; width: 100%;">
<h1>Welcome Naren</h1>
<label>Its good for u.All the best</label>
</div>
</div>
</body>
</html>
The other option is to examine event.target and see if the click came from inside the inner div.
I am attempting to use Javascript to position some of my elements on the screen/window. I am doing this to make sure that what ever the dimensions of the users screen, my elements will always be in the centre.
I know that padding & margin can also achieve this, but I am using a custom movement script called raphael.js, & in order to move my elements I need to set out my elements absolutely (its a custom home page, where you click blocks(that are links) & they fly off the screen).
My javascript function to move my elements fails to move my elements. Any suggestions on how to position my elements using javascript would be really helpful.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="dropDownMenu.js"></script>
<title></title>
<script src="javascript/raphael.js"></script> <!-- I am using a custom drawing/moving script which is why I cant put the img(id=bkImg) inside the div element -->
<script LANGUAGE="JavaScript" type = "text/javascript">
<!--
function getScreenSize()
{
var res = {"width": 630, "height": 460};
if (document.body)
{
if (document.body.offsetWidth) res["width"] = document.body.offsetWidth;
if (document.body.offsetHeight) res["height"] = document.body.offsetHeight;
}
if (window.innerWidth) res["width"] = window.innerWidth;
if (window.innerHeight) res["height"] = window.innerHeight;
alert( res["width"] );
alert( res["height"] );
return res;
}
function positionBlocksAccordingToScreenSize()
{
// The problem is that the blocks position does not change but they should?
var scrDim = getScreenSize();
var BK_WIDTH = 800;
var BK_HEIGHT = 600;
var X_OFFSET = (scrDim["width"]-BK_WIDTH) / 2; // variable that changes according to the width of the screen
var BLOCK_POS_X = [160, 80, 280, 20, 200, 400];
var BLOCK_POS_Y = [26, 203, 203, 380, 380, 380];
for ( var i=1; i<=5; i++ )
{
//document.getElementById("block"+i).setAttribute( "offsetLeft", X_OFFSET + BLOCK_POS_X[i] ); // doesn't work
//document.getElementById("block"+i).setAttribute( "offsetTop", BLOCK_POS_Y[i] ); // doesn't work
document.getElementById("block"+i).style.left = X_OFFSET + BLOCK_POS_X[i]; // doesn't work
document.getElementById("block"+i).style.top = BLOCK_POS_Y[i]; // doesn't work
}
}
-->
</script>
<style type="text/css" media="all">
<!--
#import url("styles.css");
#blockMenu { z-index: -5; padding: 0; position: absolute; width: 800px;
height: 600px; /*background-image: url("images/menuBk.png");*/ }
#bkImg { z-index: -5; position: relative; }
#block1 { z-index: 60; position: absolute; top: 26px; left: 160px; margin: 0; padding: 0; }
#block2 { z-index: 50; position: absolute; top: 203px; left: 80px; margin: 0; padding: 0; }
#block3 { z-index: 40; position: absolute; top: 203px; left: 280px; margin: 0; padding: 0; }
#block4 { z-index: 30; position: absolute; top: 380px; left: 20px; margin: 0; padding: 0; }
#block5 { z-index: 20; position: absolute; top: 380px; left: 200px; margin: 0; padding: 0; }
#block6 { z-index: 10; position: absolute; top: 380px; left: 400px; margin: 0; padding: 0; }
-->
</style>
</head>
<body onload="positionBlocksAccordingToScreenSize()" style="margin-top: 10%; text-align: center; margin-bottom: 10%; position: relative;">
<img id="bkImg" src="images/menuBk.png" width="800px;" height="600px" alt=""/>
<!-- The above image should be displayed behind the below div. I am using the raphael.js movement script, so I cannot place
this image inside the div, because it will get erased when I call raphael.clear(); -->
<div id="blockMenu">
<div id="block1"><img src="images/block1.png" width="200" height="200"/></div>
<div id="block2"><img src="images/block2.png" width="200" height="200"/></div>
<div id="block3"><img src="images/block3.png" width="200" height="200"/></div>
<div id="block4"><img src="images/block4.png" width="200" height="200"/></div>
<div id="block5"><img src="images/block5.png" width="200" height="200"/></div>
<div id="block6"><img src="images/block6.png" width="200" height="200"/></div>
</div>
</body>
</html>
You're not setting the left and top properties correctly, you need to add the unit e.g 'px' for pixels.
document.getElementById("block"+i).style.left = X_OFFSET + BLOCK_POS_X[i] + 'px';
document.getElementById("block"+i).style.top = BLOCK_POS_Y[i] + 'px';
"Would you be able to suggest a line of jQuery code that could place my elements correctly?"
The following code uses jQuery and will center an absolutely positioned element on load and on window resize.
http://jsfiddle.net/Fu3L6/
HTML...
<div id="element">Test</div>
CSS...
#element {
position: absolute;
background-color: red;
width: 200px;
}
jQuery...
$(document).ready(function () {
centerInViewport('#element');
$(window).resize(function () {
centerInViewport('#element');
});
});
function centerInViewport(e) {
$docWidth = $(document).width();
$elWidth = $(e).width();
$offset = ($docWidth - $elWidth) / 2;
$(e).css("marginLeft", $offset + "px");
}