Mouseenter and Mouseleave giving undesired results - javascript

Im having an absolute nightmare with a plugin im trying to integrate.
Im trying to make X elements on my page flip on hover, and then on mouseout revert back.
Im using the flip function, and it works fine if i hover over an element, wait a few seconds for the flip to finsih animating, and then move my cursor. If i hover quickly however, my flip happens but messes up completely, and you cant quickly move your mouse across multiple elements.
I've tried using stop() to no avail so thought I'd ask on here, I've attached a fiddle, when looking at my fiddle, quickly run your mouse across all elements and you will see what I mean
http://jsfiddle.net/5JyVC/
$('.sec-con').prepend('<div class="target" style="width:100%; height:100%; z-index:999999; cursor:pointer;top:0; left:0; display:block; position:absolute; "></div>');
$('body').on({
mouseenter:
function () {
$(this).stop(true, true).next('.sector').flip({
direction:'rl',
color:'#2d6995',
speed: 200,
content:'<span class="all-vacancies">View all Vacancies <br />in this sector.</span><span class="read-more">Click here to read more.</span>'
});
},
mouseleave: function () {
$(this).next('.sector').revertFlip();
}
}, '.target');

It's something to do with the flipLock data attribute. If you mouseout too soon flipLock is true and the revert flip wont happen causing the next mouseover to start with the wrong content. So from then on you're flipping back and forth between the same content.
If you remove the flipLock detection and return false and add stop to the animation call in flip it will revert properly.
The animation looks a bit wonky though, I'm not sure what can be done about that.
This works for me: http://jsfiddle.net/5JyVC/5/ If you move fast enough it will still mess up, not sure why that is, maybe multiple mouseover events? This is what the original flipLock intended to prevent I guess.
Maybe flipLock should be more complex, when flipped, only allow flip backs and vice versa. The current implemenation of flip and revertFlip doesn't allow for this though.

Here is an alternative way in pure css (as requested)
the javascript is here just to add the elements faster
Anyway i modified the function sothat you can add HTMLElements direct to the function that adds the various divs that needs to be flipped.
A & B, where A is the front and B is the back.
in this example i add 6 elements to the page.
here is the javascript to test the elements
var D,
flip=function(A,B){// HTMLElement,HTMLElement - no text
var box=D.createElement('div');
box.appendChild(D.createElement('div')).appendChild(A);
box.appendChild(D.createElement('div')).appendChild(B);
return box;
},
init=function(){
D=window.document;
for(var i=0,f=D.createDocumentFragment();i<6;i++){
var a=D.createTextNode('Front '+i),
b=D.createTextNode('Back '+i);
f.appendChild(flip(a,b));
}
D.getElementsByClassName('flip')[0].appendChild(f);
}
window.onload=init;
As you can see no eventlisteners or complex code as if you use css3 you totally can put the :hover on the divs without the need of javascript (mouseenter,mouseleave).
to add this animation to every element i added a class for the container of the elements.
html,body{width:100%;height:100%;margin:0;padding:0;} /* important */
.flip{
width:100%;height:100%; /* in this case the perspective center */
-webkit-perspective:1200; /* is in the page center */
}
.flip>div{
width:200px;height:160px; /* width && height of the flip box */
float:left;
margin:16px;
-webkit-transform-style:preserve-3d;
-webkit-transition:all 600ms ease;/* animation speed is 600ms */
}
.flip>div>div{
width:100%;height:100%; /*to fit the flip container*/
-webkit-backface-visibility:hidden;/* hide the back side */
line-height:160px;text-align:center;/*center the text*/
background-color:grey;/* both sides color */
}
.flip>div>:nth-child(2){
-webkit-transform:rotateY(180deg);
margin-top:-160px;/* hack so no need for position absolute*/
}
.flip>div:hover{
/*-webkit-transition:all 1000ms ease 1000ms;
want to close it slowly with a delay? */
-webkit-transform:rotateY(180deg);
}
/* no position relative or absolute which slows down ios */
this is writtenfor webkit browsers (chrom, safari, android, ios)
i made it for my ipad.
to use it with firefox and the latest ie's that support css3 you need to duplicate this -webkit styles with the -moz,-ms,-o prefixes and check the support.
this example is based on 3d so the container has also a perspective value.
and the elements flip in real 3d and so you trigger the HW GPU acceleration on the various browsers.
the html just needs that container with the class flip
using classallows you to add multiple containers with multiple flipping elements.
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>flip</title>
//add here the links to css3 or the <style>
//add here the the script or link to the script
</head>
<body><div class="flip"></div></body>
</html>
so this is very simple as you can see but from this base you can create veri impressive animations just changind the flip css.
if you need some more advanced features you can handler that with javascript event
transitionend
if you want to add the boxes manually this is all you need to write.
<div class="flip">
<div>
<div>Element1 Front</div>
<div>Element1 Back</div>
</div>
<div>
<div>Element2 Front</div>
<div>Element2 Back</div>
</div>
</div>
Want to triggerthe animation on click/mouseevent/dragevent/scrollevent whatever?
replace .flip>div:hover with .flip>div.flipped
and in javascript on event
this.parentNode.classList.toggle('flipped')
or
this.parentNode.classList.add('flipped') & this.classList.remove('flipped')
Now this is all about modern browsers and uses modern javascript&&css3 but as you want to flip something you anyway need a modern browser.
also jQuery can't flip something in ie6
like always
javascript handle the events or adds multiple elements
css to create the style of the page
html just for a basic structure.
for any other questions just ask
fiddle (test with chrome)
http://jsfiddle.net/gNB3z/2/

Related

jquery: a better way to tie an animation to scrollbar position

var AddFootnoteScrollIndicator = function(){
$('.mobileFootnote').on('scroll touchmove', function (event) {
var scrollTop = that.$mobileFootnote.scrollTop();
if (scrollTop <= 20){
var opacity = 1 - (scrollTop/20);
$('.scroll-down-indicator').css({'opacity': opacity });
}
});
};
As the user scrolls down, the indicator slowly fades out until it is gone. They scroll back up, the indicator slowly re-appears. They stop in the middle, the indicator is half-visible.
Code works fine, but modifying the opacity via .css() seems expensive. Is there a more clever way of doing this via css or...
I don't want to delay the .on() polling because the animation needs to respond quickly to the scroll.
Any ideas?
When it comes to scroll events, modifying the css via javascript is the only way to go. There is not a way with pure CSS to detect scroll positions like you can with media queries and screen sizes.
The jquery css() function is setting the element.style.opacity property under the hood. You are only one short abstraction layer from the actual element property, so it is not "expensive".
The most costly part of that call would be the $('.scroll-down-indicator') selector, as it has to perform a DOM traversal to find elements with the class name.

Fullpage.js. How to disable delay between normalizing elements?

Pacient: http://demo.imatte.us/fomru/landingpage.html
Problem: http://gyazo.com/031fe1c5413550e6e68aceef2740cefc
When window's size is changing, then we can see content of other slide. But after release the window's border, elements moving to right places with animation after small delay. How to disable this delay and animation, and force elements to stay on right positions constantly?
As #flybear pointed out, you would need to modify the plugin for it.
You would also need to change the scrollingSpeed of the plugin by using $.fn.fullpage.setScrollingSpeed(0). But this will only work if you use css3:false.
You should change the current event resize for this one:
//when resizing the site, we adjust the heights of the sections, slimScroll...
$(window).resize(function () {
// rebuild immediately on touch devices
if (isTouchDevice) {
$.fn.fullpage.reBuild();
} else {
$.fn.fullpage.setScrollingSpeed(0);
$.fn.fullpage.reBuild();
$.fn.fullpage.setScrollingSpeed(700); //default one
}
});
If you want to make it work with css3:true as well, you would need to deal with the css3 animations defined in the .fp-easings class. You probably can create another CSS class to overwrite the .fp-easings one defining a transition with 0 seconds:
//when resizing the site, we adjust the heights of the sections, slimScroll...
$(window).resize(function () {
// rebuild immediately on touch devices
if (isTouchDevice) {
$.fn.fullpage.reBuild();
} else {
$.fn.fullpage.setScrollingSpeed(0);
$('.fp-easings').addClass('.fp-no-transitions');
$.fn.fullpage.reBuild();
$.fn.fullpage.setScrollingSpeed(700); //default one
$('.fp-easings').removeClass('.fp-no-transitions');
}
});
CSS
.fp-no-easing {
-webkit-transition: all 0s ease-out !important;
transition: all 0s ease-out !important;
}
Just take into account that on every resize event, which can be fired hundreds of times when you resize the browser's window, will execute the reBuild function of the plugin, which will take care of resizing sections, updating the inner containers and scroll all the sections and slides of your site to fit the new position.
Firing this hundreds of times can cause some problems in slow computers and will slow down the page.

Why is my jQuery transition is glitchy?

I have a jQuery transition with a css overlay that will work fine if the user mouses over for a second or more....however if the user mouses over quickly then the overlay text stays put without the overlay background. Here is my jQuery code:
$(".cascade-t1").hover(function(){
$(".cascade-corner").fadeOut();
$(".overlay-t1").animate({"left": "-300px"}, 300, function(){
$(".cascade-overlay-content").fadeIn(200);
});
}, function(){
$(".cascade-corner").fadeIn();
$(".cascade-overlay-content").fadeOut(200, function(){
$(".overlay-t1").animate({"left": "130px"}, 300);
});
});
Here is the script in action
It looks like the issue is that you don't fadeIn() the .overlay-t1 text until the mouseenter animation is done, and on mouseleave you fadeOut() the text out right away before the animation. When you move your mouse in and out faster than initial the animation the code will fade out the text and then fade it in again (the issue you're seeing).
One possible solution is to slightly alter your bottom (mouseleave) function to resemble your top (mouseenter) function more closely. Something like:
$(".cascade-corner").fadeIn();
$(".overlay-t1").stop(true, true).animate({"left": "130px"}, 300, function () {
$(".cascade-overlay-content").fadeOut(200);
});
The .stop() is there to keep the animation from playing over and over when someone spams the box.
FIDDLE DEMO
Not sure how jquery animate works under the hood but it's possible it's using javascript to animate instead of css transitions. The benefit of css transitions is that it does all of the animation calculations before the animation begins and is hardware accelerated. Javascript is at the mercy of the scheduler at a very high level so it will always be choppy.
Try jquery transit.
http://ricostacruz.com/jquery.transit/

Couple Issues with jQuery Animation

I am using jQuery Animate to create a Pan-Zoom effect on an image. Overall it works well with two exceptions.
First it starts the animation and seems to hit a wall then continue to zoom in. Is there a way to prevent this and make the motion one smooth motion.
Second is the motion is a bit jerky, especially at the end. Is there a way to smooth this out? I am using easing on the page if I should try adding some form of easing. (This was testing in Firefox and Chrome and both are jerky.)
Here is a jsFiddle of the animation.
Notes: I am using jQuery 1.8.3 and I could use CSS but sticking with jQuery for cross browser compatibility. (Majority of my users are on IE unfortunately.)
HTML
<div style="width:1140px; height:500px; overflow:hidden; text-align:center;">
<img id="pan-zoom" style="width:900px; height:600px; position:relative; top:-80px; left:0;" alt="European Bee-eaters" src="http://upload.wikimedia.org/wikipedia/commons/9/96/Pair_of_Merops_apiaster_feeding.jpg" />
</div>
JS
$(window).load(function() {
$('#pan-zoom').animate({
width: '2141px',
height: '1428px',
top: '-200px',
left: '-405px'
}, 8000, function() {
// Fade In Hidden DIV
});
});
If you speed up the animation, it will appear to be smoother. The slower the animation, the more noticeable any roughness of it will be.
Changing the easing to linear seemed to help as well. The slowness at end of the default easing (swing) makes the roughness of the animation very noticeable. The code below uses linear easing and is sped up twice as fast (as well changing the outer width to 900px, as #loxxy suggested), and it looked reasonably good.
$(window).load(function() {
$('#pan-zoom').animate({
width: '2141px',
height: '1428px',
top: '-200px',
left: '-405px'
}, 4000, 'linear', function() {
// Fade In Hidden DIV
});
});
Getting a large animation to be both smooth and slow may only be possible with hardware support like WebGL. Short of that, choose between smooth and slow, whichever is more important.
Change
<div style="width:1140px; ...
To
<div style="width:900px; ...
The idea is, that before zooming in, the image is scaled to fit the parent width, which is the effect you want to remove.
Updated fidde.
EDIT : Or position absolute, as commented.
Both problems would be resolved if you used the scale function of the css transform property. I think (it has been a long time since i've user jquery and did not follow up) that the jquery.animate function is not compatible with these. You should use a plugin or write one that does if you want to keep using jquery.
In your fiddle you use the left, top, width and height properties. This will be especially jerky in webkit.
Jquery transform plugin top google result:
http://ricostacruz.com/jquery.transit/

How to create a dynamic CSS-based interface using moving content tiles?

I'm trying to figure out what the best way would be to set up a website interface that has a large centre 'tile' (basically a div with rounded corners, a variable background image, and text on it) that acts as the hub of the interface, around which I have smaller tiles which are clickable as link, e.g. one tile will lead to a photo gallery etc... However I need these smaller tiles to be moveable i.e. I would like them to visibly whisk away off the screen (in a specific direction) before the next set of tiles enters the screen.
(Ideally they would be the same set of tiles, they would simply go off screen to 'change' as it were and come back as the new set of tiles - An ideal example would be of clicking on the photo gallery tile, all the main tiles whisk away off screen, to be replaced by more tiles representing individual photos in the gallery)
I have no issues with the CSS of round corners and positioning my tiles etc... but I'm currently trying to get the tiles to actually move using the code referenced here: Alter CSS class attributes with javascript?
I can't get it to work. I've set up one of my test tiles to make just one change to the width of another test tile using the above-referenced code when it detects a mouseover event on the div, but it appears not to work.
Here's my code, if you can spot any errors, but primarily I'd also like to hear if you have any better suggestions of reaching the design state I'm looking for:
var style;
function changeFoo() {
if(typeof style == 'undefined') {
var append = true;
style = document.createElement('style');
}
else {
while (style.hasChildNodes()) {
style.removeChild(style.firstChild);
}
}
var head = document.getElementsByTagName('head')[0];
var rules = document.createTextNode(
'.tiletest2 { border:4px solid #999; background-color:#999; width: 50px; border-radius:32px; }'
);
style.type = 'text/css';
if(style.styleSheet) {
style.styleSheet.cssText = rules.nodeValue;
} else {
style.appendChild(rules);
}
if(append === true) head.appendChild(style);
}
The onmouseover event looks like this:
<div class="tiletest1" onmouseover="changeFoo()">
<br/><br/>
SAMPLE left
<br/><br/>
Try using a JavaScript library like http://jquery.com/. You can also get plugins like http://jqueryui.com/ for the kinds of effects you're describing.
I agree with TimS to go with jquery, specifically you will want to use the .animate()function.
This will make it much easier on yourself since you can easily control the speed and time the animation plays and you may be able to easily remove div(s) with the .hide() function, which gives you many options of what kind of animation you could use to close it.

Categories

Resources