In a website I'm building, I have a button with a :hover animation, and when you click the button a lot of things on the page including the button move around. My problem is that even after the button moves out from under the mouse, it doesn't update and lose its :hover effect until you move the mouse again.
Here's an example - here once you click the button it stays light blue (the hovered colour) until you move the mouse again.
function clicked() {
if (document.getElementById('mydiv').style.transform == 'translateY(70px)') {
document.getElementById('mydiv').style.transform = 'translateY(0px)';
} else {
document.getElementById('mydiv').style.transform = 'translateY(70px)';
}
};
div {
background-color: #fedcba;
padding: 20px;
display: inline-block;
}
div:hover {
background-color: #abcdef;
}
<div id="mydiv" onclick="clicked();">Click me</div>
How do I make the element update without the user needing to move the mouse again? JQuery is ok.
I think with your current CSS approach you won't be able to handle that. Try another JavaScript approach:
const el = document.getElementById('mydiv');
el.addEventListener('click', () => {
if(el.style.transform == 'translateY(50px)') {
el.style.transform = 'translateY(0px)';
} else {
el.style.transform = 'translateY(50px)';
}
el.style.background = "#fedcba";
});
el.addEventListener('mouseover', () => {
el.style.background = "#abcdef";
});
el.addEventListener('mouseout', () => {
el.style.background = "#fedcba";
});
div {
background: #fedcba;
padding: 20px;
display: inline-block;
}
<div id="mydiv">Click me</div>
If you extract the "hover" into the JS code then you can update the state of the element without the user having to move the mouse.
Related
I have a chat or go to top svg btn with white border and some of my sections element have blue and other white background
what I want to do is when the fixed btn enter the section while scrolling check its background
and add different classes in each case .
how can I do that in javascript or jquery ?
thank you
The easiest thing to do would be to have the fixed button have a background color that looks good on all sections. That way you can just style it and leave it alone.
If you have to have the color change at different sections, there are a few ways of doing that, none are easy, and only a few would have good performance.
The best way of doing this that I can think of would be:
Have the background of the fixed button be the default color.
Add a class modifier so that when you add one class it changes the style to the new color. Example: .button becomes .button.red
On each section that has to change the background of the button, add a custom data-attribute Example: <section change-button-bg="red">
Then on load
Set up a .querySelectorAll(*[change-button-bg]) so that you can run
a check on each of the sections.
Add a global variable called currentTarget
Set up an Intersection Observer on all the sections.
Have the callback function for .isIntersecting do a few things.
Update the currentTaget variable
Update the color of the button
Add a scroll listener
In the scroll listener watch the bounds.bottom of currentTarget to see which color it should be.
Then in the Intersection Observer, if it's no longer intersecting, remove the scroll listener to prevent memory leaks.
Here is a working example.
window.addEventListener('load', (event) => {
const changeBG = document.querySelectorAll('*[change-button-bg]');
let currentTarget = null;
const Observer = new IntersectionObserver((entries, Observer) => {
for (const entry of entries) {
if (entry.isIntersecting) {
currentTarget = entry.target;
addColor(true);
window.addEventListener('scroll', watchTarget);
} else {
addColor(false);
window.removeEventListener('scroll', watchTarget)
}
}
}, {threshold: 0.15});
for (const element of changeBG) {
Observer.observe(element);
}
function watchTarget() {
const bounds = currentTarget.getBoundingClientRect();
if (bounds.bottom < window.innerHeight - 80) {
addColor(false);
} else {
addColor(true);
}
}
function addColor(add) {
const btn = document.getElementById('button');
if (add) {
btn.classList.add('red');
} else {
btn.classList.remove('red');
}
}
});
body {
margin: 0;
}
section {
width: 100vw;
height: 100vh;
background: red;
}
section:nth-child(even) {
background: blue;
}
button {
position:fixed;
right: 50px;
bottom: 50px;
padding: 15px 25px;
border: none;
color: white;
background-color: blue;
cursor: pointer;
}
button.red {
background-color: red;
}
<html>
<body>
<section></section>
<section change-button-bg="red"></section>
<section></section>
<section change-button-bg="red"></section>
<section></section>
<button id="button">Top</button>
</body>
</html>
this is the solution I was looking for I did it using Intersection Observer
document.addEventListener('DOMContentLoaded',()=>{
let options = {
root:null,
rootMargin:"-570px 0px -100px 0px",
threshold:0.05
};
let Observer= new IntersectionObserver(changColor,options);
document.querySelectorAll("section").forEach(section => {
Observer.observe(section);
});
});
function changColor(elements) {
elements.forEach(el => {
if (el.isIntersecting) {
let elbg=el.target.dataset.bg;
if (elbg=="blue") { //if section data-bg== blue
// change svg button style
document.getElementById("chatting_path_7").style.fill = "#fff";
document.getElementById("to_top_Ellipse_4").style.stroke = "#fff";
} else {
document.getElementById("chatting_path_7").style.fill = "#034ea2";
document.getElementById("to_top_Ellipse_4").style.stroke = "#034ea2";
}
}
})
}
I have a quite simple scenario where I am trying to prevent the orange background on mouse down:
document.querySelector('label').addEventListener('mousedown', (event) => {
console.log('mouse down')
event.preventDefault();
})
label:active {
background: orange;
}
<label>Press mouse down</label>
Unfortunately the event.preventDefault() has no effect and the label becomes orange. (Tested in Chrome and Safari and IE11)
Can anyone explain me the reason behind that or maybe tell me how to prevent the active state programatically without hacks?
Codepen: https://codepen.io/anon/pen/pPZVrO
It seems like an old issue. If you want, you can fix it, by using pointer-events property. Also, support for the same is pretty much decent (including IE11)
label:active {
background: orange;
}
label {
pointer-events: none;
}
<label>Press mouse down</label>
Make sure you have some class or an id declared on the label element so that you don't target all of them.
JavaScript Solution - Just giving a shot
The idea is to add a class on mousedown and override it with CSS class having an :active pseudo class, and later, remove the class on mouseup .. something like
var overrideActive = function() {
var labelElm = document.querySelector('label');
var bodyElm = document.querySelector('body');
function init() {
//on mousedown, add a class and override it with css
labelElm.addEventListener('mousedown', (event) => {
event.target.className = 'disable-active';
});
//onmouseout get rid of the class
bodyElm.addEventListener('mouseup', (event) => {
labelElm.classList.remove('disable-active');
});
}
return {
init: init
}
}();
overrideActive.init();
label:active {
background: orange;
}
.disable-active:active {
background-color: transparent;
}
<label>Press mouse down</label>
You can disable mouse events via css. Adding this CSS will will prevent the background from turning orange.
label {
pointer-events: none;
}
If you don't want to do it in every case, use a class and apply the noclick class only when needed (ie, as part react's render() method, or when the page is generated, depending on the framework you're using.
.noclick {
pointer-events: none;
}
I have two borders, one on the bottom of an H1, and the other on the right hand side of a div. I have them change color if the mouse is over either element. My idea is to change both borders to be the new color when the mouse is in neither. I figure my best bet would be some sort of JavaScript logic. Something like: if the mouse is not on a, and not on b, add id1 and id2, though I don't know how this will affect my id1 and id2 when the mouse goes back to them.
Is this the right answer, or is there another way I can do this? In case you're wondering the border is 2px wide. I am very new to JavaScript. So to recap, what I want is, the borders of my h1 and div to change when the mouse hovers over them, when the mouse is on neither, I wan't both borders to change at the same time. I'm after the simplest least messy way of solving this.
You could do it by applying css only when their container is hovered. Check out the snippet!
.container {
display:block;
width:100px;
}
.container:hover h1 {
border-right:solid 2px red;
}
.container:hover div {
border-top:solid 2px blue;
}
<div class="container">
<h1>Hi there</h1>
<div>my friend</div>
</div>
You can use the onmouseleave event to handle what happens when the mouse is not on the elements.
You can have a boolean value for each element that you set to true when the user hovers over them and false when the user leaves them. Then you can have an if statement in your onmouseleave event handler that checks whether the mouse is not on either of the elements.
//Get your h1 element
//Get your div element
var onH1 = false;
var onDiv = false;
function changeBoth() {
//Change both borders
}
h1.onmouseover = function() {
onH1 = true;
//Change h1 border
}
div.onmouseover = function() {
onDiv = true;
//Change div border
}
h1.onmouseleave = function() {
onH1 = false;
if((!onH1) && (!onDiv)) {
changeBoth();
}
}
div.onmouseleave = function() {
onDiv = false;
if((!onH1) && (!onDiv)) {
changeBoth();
}
}
I have an animation triggered by a scroll event, which makes a menu slide out of view. There is also a button that when clicked brings the menu back into view.
Because the menu can be closed by scrolling, when the user clicks the button to bring the menu in, if they scroll during this period of the animation, the menu disappears again without the animation completing.
I have put together a simplified version of the animation here http://codepen.io/emilychews/pen/evbzMQ
I need to temporarily prevent the scroll function working after the button is clicked, which I'm assuming would be best done with the setTimeout() method on the click function? I've tried a number of things but can't seem to solve it/ get it to work.
Any help would be awesome. For quick reference as well the code is below
JQUERY
jQuery(document).ready(function($){
// slide menu to left on scroll
function hideOnScroll() {
$(window).scroll(function() {
if ( $(document).scrollTop() > 1) {
$('.menubox').css('left', '-25%');
}
});
}
hideOnScroll(); // call hideOnScroll function
// click handler to bring menu back in
$('.mybutton').on('click', function() {
$('.menubox').css('left', '0%');
var scrollPause = setTimeout(hideOnScroll, 2000) // temporarily pause hideOnScroll function
});
}); //end of jQuery
CSS
body {
margin: 0;
padding: 0;
height: 200vh;}
.menubox {
top: 100;
position: fixed;
width: 20%;
height: 100%;
background: red;
padding: 10px;
color: white;
transition: all 2s;
}
.mybutton {
position: fixed;
left: 40%;
top: 50px;
padding: 5px 10px;
}
HTML
<div class="menubox">Menu Box</div>
<button class="mybutton">Click to bring back menu</button>
** Also please note I've simplified the animation for the sake of the forum, the actual animation function contains Greensock code, but I didn't want to include this in case it confused the issue. I can't therefore just use the .addClass() and .removeClass() or have a workaround that changes the given CSS or scrollTop() values. I need to disable the hideOnScroll() function when the button is clicked for the duration of the click invoked animation - which in the examples is 2s. Thus I think the only way to achieve this is with the setTimeOut() method (i may be wrong on this). But I can't get it to work.
Many thanks
Emily
you can simply check the offset is complete.
function hideOnScroll() {
$(window).scroll(function() {
if ( $(document).scrollTop() > 1) {
if( $('.menubox').offset().left == 0 ){
$('.menubox').css('left', '-25%');
}
});
}
http://codepen.io/anon/pen/aJXGbr
I have made a few changes in your javascript. Have a look
var animating = false;
$(document).ready(function(){
function hideOnScroll() {
$(window).scroll(function() {
event.preventDefault();
if ( $(document).scrollTop() > 1 && !animating){
console.log("Hiding")
animating = true;
$('.menubox').animate({'left': '-25%'},2000,function(){
animating = false;
});
}
});
}
hideOnScroll();
$('.mybutton').click(function() {
var pos = $(window).scrollTop();
animating = true;
$('.menubox').animate({'left':'0%'},2000,function(){
console.log("Finished Opening");
animating = false;
});
console.log("Animating Open");
var siId = setInterval(function(){
if(animating){
console.log("Preventing Window Scrolling.");
$(window).scrollTop(pos);
}
else{
console.log("Stopping setInterval");
animating = false;
clearInterval(siId);
}
},0);
});
});
This will stop your browser window from scrolling until your Menu Open Animation is finished.
Also I have removed the transitionproperty from style.
Tested in Google Chrome.
Kindly inform me if i have misinterpreted your question.
How to apply event of mousemove, so we can get effect like vlc player has for seekbar, or Youtube has for VideoTitle.
i.e : On mouse movement show title, if mouse not moved then hide title
Why need : I am developing website something like video library, there is one seekbar which I want to disable when mouse is not moved till someminute, and if mouse move then make it visible.
What I Did :
document.body.onmousedown = function() {
$(".myPrivateSeek").hide();
};
document.body.onmouseup = function() {
$(".myPrivateSeek").show();
};
althought its wroking,Unfortunately its not so much helpfull,
You can make use of mousemove event.
Below is a working code for that , you can play with it here in JSfiddle and modify as you want.
HTML
<div id="item">
<p>This is my item</p>
<div class="tooltip">Tooltip</div>
</div>
CSS
#item {
position: relative;
background: #CCC;
}
#item .tooltip {
position: fixed;
width: 80px;
height: 30px;
background: #06F;
z-index: 10;
display: none;
}
jQuery
$(document).ready(function() {
$("#item").on('mousemove', function(e) {
$('.tooltip').css('left', e.pageX + 10).css('top', e.pageY + 10).css('display', 'block');
});
$("#item").mouseout(function() {
$('.tooltip').css('display', 'none');
});
});
If you would like it so that on mouse movement your element appears then after a specified time of no movement it automatically disappears you could implement the following:
$(document).ready(function () {
var timeoutId;
//Replace document.body with the element you wish the mouse movement to be recognised within.
$(document.body).on('mousemove', function () {
//Checks if an existing timeout function exists, if so remove it.
if (timeoutId) {
clearTimeout(timeoutId);
}
$(".myPrivateSeek").show();
//Set a callback for how long to wait after the mouse has stopped moving to hide your element.
timeoutId = setTimeout(function () {
$(".myPrivateSeek").hide();
}, 1000); //The time in milliseconds to wait.
});
});