Why does the last container flicker? - javascript

I'm trying to create a set of div's that will animate on hover. I'm using jQuery and the HoverIntent plugin to animate it.
The HTML
<body>
<div class="wrapper">
<div class="grow" style="background-color:#03045E;"></div>
<div class="grow" style="background-color:#0077B6;"></div>
<div class="grow" style="background-color:#00B4D8;"></div>
<div class="grow" style="background-color:#90E0EF;"></div>
</div>
</body>
... and the JS Code
$(function() {
$('.grow').hoverIntent({
over : function() {
$('.grow').animate({
'width':'15%'
},{duration:400,queue:false});
$(this).animate({
'width':'55%'
},{duration:400,queue:false});
},
out : function() {
//we need to check if the mouse is outside the main object to fire a back to original state. Hence, the mouse out effect on the containers itself should do nothing.
}
});
$('.wrapper').hoverIntent({
out : function() {
$('.grow').animate({
'width':'25%'
});
}
});
});
It is available here - https://jsfiddle.net/be0u3hfx/12/
I cant seem to understand why the last div flickers on hover of any div! Help!?

It's because during the size changes, the widths of the elements will occasionally amount to more than 100% total, and when that happens, the browser briefly wraps the last element, making it appear below the first. To prevent that, add display: flex; to your wrapper's CSS rules.
Fixed code:
$(function() {
$('.grow').hoverIntent({
sensitivity: 1, // sensitivity threshold
interval: 10, // milliseconds for onMouseOver polling interval
timeout: 500, // number = milliseconds delay before onMouseOut
over: function() {
$('.grow').animate({
'width': '15%'
}, {
duration: 400,
queue: false
});
$(this).animate({
'width': '55%'
}, {
duration: 400,
queue: false
});
},
out: function() {}
});
$('.wrapper').hoverIntent({
over: () => {},
out: function() {
$('.grow').animate({
'width': '25%'
});
}
});
});
* {
box-sizing: border-box;
}
body {
background-color: black;
margin: 0 auto;
padding: 10px;
height: 100vh;
width: 100%;
}
.wrapper {
padding: 10px;
height: 100%;
background: #fff;
display: flex;
}
.grow {
box-sizing: border-box;
height: 100%;
/* Original height */
width: 25%;
/* Original width */
float: left;
/* Just for presentation (Not required) */
position: relative;
/* Just for presentation (Not required) */
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.hoverintent/1.10.1/jquery.hoverIntent.min.js"></script>
<div class="wrapper">
<div class="grow" style="background-color:#03045E;"></div>
<div class="grow" style="background-color:#0077B6;"></div>
<div class="grow" style="background-color:#00B4D8;"></div>
<div class="grow" style="background-color:#90E0EF;"></div>
</div>

Related

How to animate a text that both slides and fades in using JavasScript and/or JQuery?

I have searched on google and here but not been able to implement any of the tips. I'm not good at JS at all. What I want to do is to have a single line of text fade in while it's floating upwards when you hover on a div and the reverse when you stop hovering.
I have not been able to use both the slide and fade effects.
Here is my code using JQuery 2.3.1
$(function() {
// DOM ready
$('#card1').hover(
function() {
$('#artist1').slideDown();
},
function() {
$('#artist1').slideUp();
});
});
#artist1 {
position: absolute;
top: 100px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<div id="card1" style="width: 100px; height: 100px; background-color: red;">
<h4 id="artist1" class="artistname ">testname</h4>
</div>
See changes to style and tags:
$(function() {
var slideDuration = 300;
$('#card1').hover(
function() {
$('#artist1').stop(true, true)
.fadeIn({ duration: slideDuration*3, queue: false })
.css('display', 'none').slideDown(slideDuration);
},
function() {
$('#artist1').stop(true, true)
.fadeOut({ duration: slideDuration*1.5, queue: false })
.slideUp(slideDuration*3);
}
)
});
#artist1 {
position: relative;
top: -10px;
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<div id="card1" style="width: 100px; height: 100px; background-color: red;"></div>
<h4 id="artist1" class="artistname ">testname</h4>

Use jQuery to animate the re-position of DIV's after fadeOut (fiddle)?

To get a better idea of what I'm trying to do, I have this fiddle:
https://jsfiddle.net/tfisher9180/7efagjhj/1/
When you click the button 3 squares fade out, and then afterwards the orange square immediately snaps up because of the absence of the others.
I want to know if there's a way to animate that to look more fluid so that the orange box slides up as well.
.square {transition: all 0.3s linear;}
This did not work as I expected.
UPDATE:
Marking #anied as correct answer for working with me a bit and helping to fix positioning. Everyone's solutions were awesome though and worked nicely. +1 for all and will have to try out a few to see which looks best!!!
So, the problem with using a CSS transition here is that there is no CSS property of the orange box that is changing when the boxes around it disappear-- it is simply reflowing to the new position in the DOM based on the change the display property of these other boxes. I think if you want this to work you will have to write a custom bit of jQuery code that fades the boxes out but doesn't immediately hide them, but instead slides them up and out of sight.
Try something like this:
$('#sort').on('click', function() {
$('.square').each(function() {
if (!$(this).hasClass('square-orange')) {
$(this).animate({'opacity' : 0}, 400, 'swing', function () {
$(this).slideUp();
});
}
});
});
edit:
Regarding the skip-- not really sure exactly, but I tried replacing the slideUp with a custom replacement and it seemed to resolve it:
$('#sort').on('click', function() {
$('.square').each(function() {
if (!$(this).hasClass('square-orange')) {
$(this).animate({'opacity': 0}, 400, 'swing', function() {
$(this).animate({'height': 0}, 400, 'swing');
});
}
});
});
edit (again): actually, looking now I see that one problem is that the top .row still is retaining height after the boxes within slide-up.... you might need to slide that up as well, depending on your requirements..
edit:
OK, last time, fixed your positioning a bit-- I think this works:
$('#sort').on('click', function() {
$('.square').each(function() {
if (!$(this).hasClass('square-orange')) {
$(this).animate({'opacity': 0}, 400, 'swing', function() {
$(this).animate({'height' : 0}, 400, 'swing');
});
}
});
});
.clearfix:after {
content: "";
display: table;
clear: both;
}
.row {
display: block;
clear: both;
}
.square {
width: 60px;
height: 60px;
display: block;
float: left;
margin-right: 10px;
margin-bottom: 10px;
}
.square-red {
background-color: red;
}
.square-blue {
background-color: blue;
}
.square-orange {
background-color: orange;
}
.square-purple {
background-color: purple;
}
#sort {
margin-top: 30px;
background-color: #414141;
border: 0;
color: #f2f2f2;
padding: 10px 15px;
cursor: pointer;
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<div class="row row-top clearfix">
<div class="square square-red"></div>
<div class="square square-blue"></div>
</div>
<div class="row row-bottom clearfix">
<div class="square square-orange"></div>
<div class="square square-purple"></div>
</div>
</div>
<button id="sort">Sort Orange</button>
Use this jquery:
$('#sort').on('click', function() {
$("row").eq(0).css("min-height",$(".square-red").height()+"px");
$(".square:not(.square-orange)").fadeOut().slideUp();
$(".square-red").parent().slideUp();});
Try This:
$('#sort').on('click', function() {
$('.square').each(function() {
if (!$(this).hasClass('square-orange')) {
$(this).animate({
opacity: 0
}, 500, function() {
$(this).slideUp(100);
});
}
});
});
https://jsfiddle.net/7efagjhj/7/
You can set the position of .square-orange and #sort to absolute and set top .position().top before .fadeOut() begins, use .promise(), .animate() to animate .square-orange when .square:not(.square-orange) elements animation completes
$('#sort').on('click', function() {
$(this).add(".square-orange")
.each(function() {
$(this).css({
"position": "absolute",
top: $(this).position().top
})
})
$('.square:not(.square-orange)').each(function() {
$(this).fadeOut();
})
.promise()
.then(function() {
$(".square-orange")
.animate({
top: 20
}, 1000, "linear")
})
});
.square {
width: 60px;
height: 60px;
display: inline-block;
}
.square-red {
background-color: red;
}
.square-blue {
background-color: blue;
}
.square-orange {
background-color: orange;
}
.square-purple {
background-color: purple;
}
#sort {
margin-top: 30px;
background-color: #414141;
border: 0;
color: #f2f2f2;
padding: 10px 15px;
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<div class="row">
<div class="square square-red"></div>
<div class="square square-blue"></div>
</div>
<div class="row">
<div class="square square-orange"></div>
<div class="square square-purple"></div>
</div>
</div>
<button id="sort">Sort Orange</button>
jsfiddle https://jsfiddle.net/7efagjhj/8/

Count back percentage using JQuery

I have the code below where I'd like to the numbers count back to 0% once hover the object out. Also I can't figure our how to make the value disappear again as it was on load. Could you please help me solve this.
Thanks in advance.
HTML
<div class="container">
<div class="fill" data-width="80%"></div>
</div>
<div class="container">
<div class="fill" data-width="50%"></div>
</div>
CSS
.container {
position: relative;
width: 300px;
height: 30px;
background-color: blue;
margin: 10px auto;
}
.fill {
height: 100%;
width: 0;
background-color: red;
line-height: 30px;
text-align: left;
z-index: 1;
text-align: right;
}
JQuery
$(function() {
$('.container').hover( function(){
var width=$(this).find(".fill").data('width');
$(this).find(".fill").animate({ width: width }, {
duration:800,
step: function(now, fx) {
$(this).html(Math.round(now) + '%');
}
});
},
function(){
$(this).find(".fill").animate({ "width": "0px" }, 800);
});
});
jsFiddle http://jsfiddle.net/zp8pe069/
jsBin demo
CSS: set overflow: hidden to .fill to prevent the text being visible after the animation ends.
HTML: remove % from the data attribute
JS and here you go. all you need:
$('.container').hover(function( e ){
var $fill = $(this).find(".fill");
var width = $fill.data('width');
$fill.stop().animate({width: e.type=="mouseenter" ? width+"%" : "0%" }, {
duration : 800,
step : function(now) {
$(this).html(Math.round(now) + '%') ;
}
});
});
Note also the use of the .stop() method, if you hover multiple time hysterically :) it'll prevent endless animations.

Mobile slider only responding every other touch

I am trying to build a slider based upon http://css-tricks.com/the-javascript-behind-touch-friendly-sliders/. My goal is to make a horizontal, mobile-only slider that allows you to slide back and forth between the steps in a registration process.
The code works for the most part, but the slider only moves every other touch, and I'm not sure why.
http://codepen.io/anon/pen/zKhao
HTML:
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<div class="visible-xs mobile-tabs">
<div class="slider-wrap">
<div class="slider" id="slider">
<div class="holder">
<div class="slide-wrapper">
<h4 class="complete">Before you begin</h4>
</div>
<div class="slide-wrapper">
<h4 class="complete">1. Terms & Conditions</h4>
</div>
<div class="slide-wrapper">
<h4 class="current">2. Teams</h4>
</div>
<div class="slide-wrapper">
<h4>3. Add-Ons</h4>
</div>
<div class="slide-wrapper">
<h4>4. Review & Submit</h4>
</div>
</div>
</div>
</div>
</div>
CSS:
a
{
color: #5fa4db;
text-decoration: none;
}
.mobile-tabs
{
height: 45px;
overflow: hidden;
border-bottom: 1px solid #f1f2f4;
white-space: nowrap;
margin-bottom: 10px;
}
.mobile-tabs h4
{
color: #9fa9b2;
display: inline-block;
padding-right: 10px;
padding-bottom: 10px;
font-weight: bold;
font-size: 18px;
}
.mobile-tabs h4.current
{
border-bottom: 5px solid #5fa4db;
color: #0f2034;
}
.mobile-tabs h4.complete
{
color: #5fa4db;
}
/* CSS for mobile tab slider.
Source: http://css-tricks.com/the-javascript-behind-touch-friendly-sliders/
*/
.mobile-tabs .animate {
transition: transform 0.3s ease-out;
}
.mobile-tabs .slider-wrap {
width: 100%;
position: absolute;
}
.mobile-tabs .slider {
width: 100%;
height: 100%;
overflow: hidden;
}
.mobile-tabs .ms-touch.slider {
overflow-x: scroll;
overflow-y: hidden;
-ms-overflow-style: none;
/* Hides the scrollbar. */
-ms-scroll-chaining: none;
/* Prevents Metro from swiping to the next tab or app. */
-ms-scroll-snap-type: mandatory;
/* Forces a snap scroll behavior on your images. */
-ms-scroll-snap-points-x: snapInterval(0%, 1%);
/* Defines the y and x intervals to snap to when scrolling. */
}
.mobile-tabs .holder {
width: 300%;
overflow-y: hidden;
}
.mobile-tabs .slide-wrapper {
float: left;
position: relative;
overflow: hidden;
}
.mobile-tabs .slide div {
width: 300px;
height: 500px;
z-index: 0;
}
JavaScript:
if (navigator.msMaxTouchPoints) {
$('#slider').addClass('ms-touch');
$('#slider').on('scroll', function () {
$('.slide-image').css('transform', 'translate3d(-' + (100 - $(this).scrollLeft() / 6) + 'px,0,0)');
});
} else {
var slider = {
el: {
slider: $("#slider"),
holder: $(".holder")
},
slideWidth: $('#slider').width(),
touchstartx: undefined,
touchmovex: undefined,
movex: 0,
index: 0,
longTouch: undefined,
init: function () {
this.bindUIEvents();
},
bindUIEvents: function () {
this.el.holder.on("touchstart", function (event) {
slider.start(event);
});
this.el.holder.on("touchmove", function (event) {
slider.move(event);
});
this.el.holder.on("touchend", function (event) {
slider.end(event);
});
},
start: function (event) {
// Test for flick.
this.longTouch = false;
setTimeout(function () {
window.slider.longTouch = true;
}, 250);
// Get the original touch position.
this.oldx = this.movex;
// The movement gets all janky if there's a transition on the elements.
$('.animate').removeClass('animate');
},
move: function (event) {
// Continuously return touch position.
this.touchmovex = event.originalEvent.touches[0].pageX;
// Calculate distance to translate holder.
this.movex = -this.oldx - this.touchmovex;
// Defines the speed the images should move at.
var panx = 100 - this.movex / 6;
if (this.movex < 600) { // Makes the holder stop moving when there is no more content.
this.el.holder.css('transform', 'translate3d(-' + this.movex + 'px,0,0)');
}
},
end: function (event) {
}
};
slider.init();
}
In order to emulate the issue, you'll have to view the code on a mobile device (or use Chrome's mobile emulation) and try to slide the slider back and forth. It will move, but only every other time you attempt to slide it.
I am completely lost, and any help will be appreciated.
This isn't really an answer, per se, but I've decided to throw the entire thing out and use jquery UI's Draggable feature to do what I need to do.
http://jqueryui.com/draggable/#constrain-movement

JQuery Masonry -- expand div's over other div's

I'm making something similar to an iphone layout (a bunch of tiles with pictures/numbers that you can click on to get more information). After the layout has been set, I'd like a click-event to expand one of the tiles to be full screen. Right now, it moves the tiles so that the layout is re-adjusted. Is it possible to get masonry to stop rendering so that one tile get's enlarged over the other tiles?
The following is what I've tried (but unsuccessfully). Note: It uses d3.js to generate the div's for masonry to use.
function drawGrid(divname,orders)
{
var mydiv = d3.select(divname);
$(divname).masonry({
itemSelector: '.g1',
isAnimated: true,
//isResizable: true
});
var myd = mydiv.selectAll("div");
var mygs = myd.data(orders,function(d){ return d.orderid;})
.enter().append("div")
.attr("class","g1")
.append("g");
var x1 = mygs.append("div")
.attr("class","tickerdiv")
.text(function(d){ return d.ticker; });
var ActiveOrder = "1";
$(divname+' .g1').click(function() {
//$(this).show('maximised');
console.log("clicked")
$(this).animate({"display":"none","position": "absolute",
"top": "0",
"left": "0",
"width": "100%",
"height": "100%",
"z-index": 1000 }, 1000);
});
var x = [];
x.redraw = function(o)
{
x1.text(function(d){ return d.ticker; });
}
return x;
}
and from the css file:
.g1 { min-height:80px; width: 100px; margin: 15px; float: left; background-color: RGB(223,224,224); border-radius: 10px; vertical-align: middle; text-align: center; padding-top: 20px;}
EDIT Ok, my first answer was not useful here - absolute positioning won't work in case of masonry's/Isotope's relatively positioned container with absolute positioned elemens contained therein; the solution is rather to take the content of a masonry/Isotope element out of the DOM on click and append it temporarily to the body. You can see the basic idea in my dirty swedish sandbox
<!-- masonry/Isotope item large -->
<div class="item large">
<div class="header">
<p>Click here</p>
</div>
<div class="minimised">
<p>Preview</p>
</div>
<div class="maximised">
<p>Content</p>
<button id="screen-overlay-on">Screen overlay on</button>
<div id="screen-overlay-background"></div>
<div id="screen-overlay-content">
<p>Content</p>
<button id="screen-overlay-off">Screen overlay off</button>
</div>​
</div>
</div>
<script type="text/javascript">
$(document).ready(function(){
$('#screen-overlay-on').click(function(){
var sob = $('#screen-overlay-background').detach();
var soc = $('#screen-overlay-content').detach();
sob.appendTo('body');
soc.appendTo('body');
$('#screen-overlay-background').toggleClass("active");
$('#screen-overlay-content').toggleClass("active");
});
$('#screen-overlay-background, #screen-overlay-off').click(function(){
$('#screen-overlay-background').toggleClass("active");
$('#screen-overlay-content').toggleClass("active");
});
});
</script>
With CSS like
#screen-overlay-background {
display: none;
position: fixed;
top: 0;
left: 0;
height: 100%;
width: 100%;
background-color: #333;
zoom: 1;
filter: alpha(opacity=50);
opacity: 0.5;
z-index: 1000;
}
#screen-overlay-content {
display: none;
position: absolute;
top: 50%;
left: 50%;
height: 240px;
width: 320px;
margin: -120px 0 0 -160px;
background-color: #FFF;
z-index: 1000;
}
#screen-overlay-background.active, #screen-overlay-content.active {
display: block;
}
You can add a :hover to the element in css and change the z-index. You could easily change this on click with a class as well...
.item {
z-index:1
}
.item:hover{
z-index:2500;
}

Categories