I'm brand spankin' new to Javascript. Here's what I want to do. I want an array of square tiles covering the window and I want them to flip over when the mouse goes over them. I already have a single tile. See the Jsfiddle below.
http://jsfiddle.net/V7cS8/
I would like it so that the tile will flip over completely to the back side, even if the user doesn't hover for the entire animation length (basically, even if the hover is only very brief, I want it to commit to rotating). I want it to hold its flipped state for some minimum amount time and then return if the user is no longer hovering.
Should I be trying to do this entirely in javascript or still using a lot of CSS?
You don't need JavaScript/jQuery at all. Replace all .flip references in your CSS by :hover: http://jsfiddle.net/V7cS8/1/
For delays, you can use transition-delay: 1s.
Apply transition-delay:1s; (delay 1 second, with vendor prefixes) to the normal selector, and transition-delay:0s to the :hover selector. The result is that the backflip will be delayed for 1 second.
Demo: http://jsfiddle.net/s9xcP/2/
Outcome of comment chain: When existing animations have to be completed first, regardless of the hover state, a JavaScript timeout have to be used:
Demo: http://jsfiddle.net/nY8U8/224/
$(function(){
$('.box').hover(function(){
var $this = $(this);
// If not not-ready, do nothing
// By default, the value is `undefined`, !undefined === true
var not_ready = $this.data('box-hover-not-ready');
if (!not_ready) {
$this.addClass('hover');
} else {
// If bosy, defer hover transition
$this.data('box-hover-hovered', true);
}
}, function() {
var $this = $(this);
$this.removeClass('hover');
// Mark state as "busy"
$this.data('box-hover-not-ready', true);
var timeout = setTimeout(function() {
var hovered = $this.data('box-hover-hovered');
if (hovered) {
// If a hover transition is deferred, activate it now.
$this.addClass('hover');
$this.data('box-hover-hovered', false);
}
// Mark state as "not busy"
$this.data('box-hover-not-ready', false);
}, 2000); /* 2 seconds*/
// Remove previous timeout, set new one.
clearTimeout($this.data('box-hover-timeout'));
$this.data('box-hover-timeout', timeout);
});
});
Related
I am trying to apply the gradient effect, for example, if my mouse passes a grid cell it will light at first but the more I move my mouse towards that particular cell it will gradually get lighter. Here is my project https://repl.it/#antgotfan/etch-a-sketch and here is a working example (not mine btw), https://codepen.io/beumsk/pen/dVWPOW (just click on the gradient and will see the effect)
I am trying to use "this" and event.target to solve this problem but it is not working. I also tried to use fadeIn with jQuery but it is not my desired effect.
function incrementOpacity() {
let opacity = 0.1;
$(".cell").hover((event) => {
$(event.target).css({"opacity": `${opacity += 0.1}`,
"backgroundColor": "#f5f5f5"})
});
}
In the function, the opacity will increase forever but will stay white.
The issue is setting let opacity = 0.1; outside of the .hover event. The value should be based off of the cell being hovered, so fetch it inside the event via event.target.style.opacity. Also, make sure it is parsed correctly as a float to allow correct incrementing (parseFloat()):
function incrementOpacity() {
$(".cell").hover((event) => {
let opacity = parseFloat(event.target.style.opacity);
$(event.target).css({"opacity": `${opacity + 0.1}`, "backgroundColor": "#f5f5f5"})
});
}
Here is the updated Repl.it for reference: https://repl.it/repls/GreenDigitalWireframe
Couple of optional changes; added check for maximum opacity. Anything over 1 is redundant. Also consider using mouseenter for function so opacity is only increased when hovered on, and not hovered off:
function incrementOpacity() {
$(".cell").mouseenter((event) => {
let opacity = parseFloat(event.target.style.opacity);
if(opacity <= 0.9){
$(event.target).css({"opacity": `${opacity + 0.1}`, "backgroundColor": "#f5f5f5"})
}
});
}
Edit: For clarification, the reason using let opacity = 0.1 in conjunction with ${opacity += 0.1} doesn't work is that in every instance of .hover, the value opacity was being incremented by 0.1, but never reset. Essentially, after 9 (or 10) iterations, opacity was at a value greater than 1, so each cell was "filled" instantly.
2nd Edit: To prevent issue with assigning multiple handles for the .hover (or .mouseenter) function, add event unbinding before setting:
function incrementOpacity() {
$(".cell").off("mouseenter");
$(".cell").mouseenter((event) => { ... });
}
...
function getRandomColors() {
$(".cell").off("mouseenter");
$(".cell").mouseenter((event) => { ... });
}
Also, make sure the bound event is consistent between the two functions, either .hover or .mouseenter.
I am working on a Wordpress shortcode for generating dynamically circles.
At my current version I have a problem with saving my current and my last hover state.
Here is a fiddle
I have a problem displaying the text under the circles. The text should be displayed from the last hovered circle until I hover over a new one.
Is there maybe a better solution to my problem?
I think my problem is in the hover end.
[...] ,function () {
$contentBoxPrevious = $contentBoxCurrent;
$contentBoxCurrent.removeClass('active-text');
$(this).removeClass('hover active');
}
Move this line
$contentBoxPrevious.removeClass('active-text');
from the handleOut function to the middle of handleIn function like this https://jsfiddle.net/eu0jcmh0/
What you were doing wrong was that you were removing the "active-text" class every time you moused out of the element instead of removed it when you moused on another element, hope I helped!
Your code looked way too complicated...
So I just rewrote it my way to achieve what I think you want as a result.
Here's the code:
$(document).ready(function() {
// Set all texts invisible
$(".text-content").css({
"opacity": 0
});
// Declare previous and active indexes vars
var previous_index;
var active_index;
$(".icon-circle").hover(function() {
// On mouseenter, getting this index.
active_index = $(this).data("index");
// Show associated text.
$(this).parent().find(".text-content").css({
"opacity": 1
});
// Hide previous associated text.
if (active_index != previous_index) {
$("[data-index='" + previous_index + "']").parent().find(".text-content").css({
"opacity": 0
});
}
}, function() {
// On mouseout, just keeping previous index...
previous_index = active_index;
});
});
Working Fiddle.
enter image description here
I'm trying to create an animation where if you click the button the circles animate around the path and changes size. I'm not sure how i would cycle the classes on the next click ?
http://bluemoontesting.co.uk/bluemoon2016/people.html
I'm using an svg and have targeted the elements with this so far:
<script>
$(".animate-slider").click(function() {
$('.st7').toggleClass("top-left");
$('#XMLID_292_').toggleClass("left");
$('#XMLID_293_').toggleClass("center-right");
$('#XMLID_297_').toggleClass("top-right");
$('#XMLID_301_').toggleClass("top");
$('#XMLID_283_').toggleClass("top-center");
});
</script>
If anyone could help me i'd be very grateful :)
Thanks
I would take a little different approach. Instead of toggling classes, to get it to move to more than two positions, you will need to cycle the classes assigned to each element instead. Storing the class names in an array would allow you to move them in the array to cycle the position that each element moves to next. I created a simplified example.
$(document).ready(function () {
var steps = ['right', 'bottom-right', 'bottom-left', 'left', 'top'],
allClasses = steps.join(' ');
$('#go').click(function() {
$('#a').removeClass(allClasses).addClass(steps[0]);
$('#b').removeClass(allClasses).addClass(steps[1]);
$('#c').removeClass(allClasses).addClass(steps[2]);
$('#d').removeClass(allClasses).addClass(steps[3]);
$('#e').removeClass(allClasses).addClass(steps[4]);
steps.push(steps.shift()); // move first element to the end
// to cycle in the other direction you would pop and unshift instead
// steps.unshift(steps.pop()); // move last element to the beginning
});
});
You could just use setInterval like so:
var $st7 = $('.st7'); //class selectors can be expensive, so cache them
function rotate() {
$st7.toggleClass("top-left");
$('#XMLID_292_').toggleClass("left");
$('#XMLID_293_').toggleClass("center-right");
$('#XMLID_297_').toggleClass("top-right");
$('#XMLID_301_').toggleClass("top");
$('#XMLID_283_').toggleClass("top-center");
}
//2000 is milliseconds, so that's two seconds
var rotateIntervalId = setInterval(rotate, 2000);
//optionally consider stopping/starting the effect on mouse hover/exit
$('#Layer_1').on('hover', function() {
clearInterval(rotateIntervalId);
}).on('blur', function() {
rotateIntervalId = setInterval(rotate, 2000);
});
So I have 2 divs. One is "top" and one is "menu." I got "menu" to fade in when you hover on "top" in JQuery, as shown:
$(".top").mouseover(function(){
$(".menu").fadeIn(200);
});
$(".top").mouseout(function(){
$(".menu").fadeOut(200);
});
But I want to make it so if I'm also hovering on "menu," "menu" will stay faded in. How would I do this?
I believe this will do it for you. It waits half a second before hiding the menu. If the user hovers over the menu in that time, then it cancels the hide operation.
var timer;
$(".top").mouseover(function(){
clearTimeout(timer);
$(".menu").fadeIn(200);
});
$(".top, .menu").mouseout(function(){
timer = setTimeout(function() {
$(".menu").fadeOut(200);
}, 500);
});
$(".menu").mouseover(function() {
clearTimeout(timer);
});
Add a variable that remembers if you are hovering on the menu:
var isHoveringMenu;
$(".menu").mouseover(function(){
isHoveringMenu = true;
});
$(".menu").mouseout(function(){
isHoveringMenu = false;
$(".menu").fadeOut(200); // you probably want this here
});
$(".top").mouseover(function(){
$(".menu").fadeIn(200);
isHoveringMenu = true; // not necessary, but sounds good
});
$(".top").mouseout(function(){
if (!isHoveringMenu) {
$(".menu").fadeOut(200);
}
});
You may want to tweak this slightly -- the best solution depends on the spatial relationship between the two divs, so we 'd need to see the layout first.
THE SITUATION
I have a series of divs setup to contain various content:
<div id="main">
<div id="about"></div>
<div id="contact"></div>
<div id="flickr"></div>
<div id="twitter"></div>
</div>
I also have a nav which fades in and out specific divs from above (using either the animate or fade functions).
THE PROBLEM
I want to be able to check when all of the divs are hidden, when using the nav - so that i can trigger an event when all of the divs are hidden.
//Custom animation function.
jQuery.fn.fadeThenSlideToggle = function(speed, easing, callback) {
if (this.is(":hidden")) {
return this.slideDown({duration: 500, easing: "easeInOutCirc"}).animate({opacity: 1},700, "easeInOutCirc", callback);
} else {
return this.fadeTo(450, 0, "easeInOutCirc").slideUp({duration: 500, easing: "easeInOutCirc", complete: callback});
}
};
//example nav items.
$('#toggleContact').click(function() {
if (!$("#contact .tab").is(':animated')) {
$('#contact .tab').fadeThenSlideToggle(); //custom animation function
}
});
$('#toggleAbout').click(function() {
if (!$("#about .tab").is(':animated')) {
$('#about .tab').fadeThenSlideToggle();
}
});
//example check to see if all divs are hidden.
if((($(":hidden", '#main').length == 3) { //3 not 4 due to delay :S
}
However, this is proving to be difficult as the check is always one div out due to the delay on the fade function updating the div to hidden.
Is there any robust way to check if all divs are hidden? Initialising the check when clicking on an item in the nav and taking into account that each div takes a certain duration to actually set to hidden once the item has been clicked?
EDIT- I'd like a solution that includes the 'check for hidden divs', not just where i should put it.
You can attach an event to the completion of the fade:
$("#MyDiv").fade(100,function(){
DoSomething();
});
Add a callback function to your custom animation method, call this callback, if supplied, in the callback code for the animation to allow you to append some stuff to do after the animation is complete. I would depend on the state being what you expect once the animation is done.
$('#toggleContact').click(function() {
if (!$("#contact .tab").is(':animated')) {
$('#contact .tab').fadeThenSlideToggle( function() {
// since this is the callback, we assume that the animation
// has hidden all but one of the tabs
... more stuff to do after the animation is complete ...
});
}
});