how to animate nested divs - jquery? - javascript

I have some code, that simulate google images effect.
How can I animate nested divs in div class="productBox", not only this div???
I want to change height of "imageProduct" class during animation also.
Here this code on jsFiddle: http://jsfiddle.net/S2svG/57/
Here is html:
<div class="productBox">
<div class="productImage"><img src="http://some_image.jpg"></div>
<div class="productTitle">Product title</div>
<div class="productDescription">Here is description of the product.</div>
<div class="buyButton">Buy this!</div>
</div>
And js:
$(function(){
$.fn.popOut=function(user_opts){
return this.each(function(){
var opts=$.extend({
useId:"poppedOut",
padding:20,
border:0,
speed:200
},user_opts);
$(this).mouseover(function(){
// kill any instance of this already
$("#"+opts.useId).remove();
// make a copy of the hovered guy
var $div=$(this).clone();
// setup for prelim stuff
$div.css({
"position":"absolute",
"border":opts.border,
"top":$(this).offset().top,
"left":$(this).offset().left,
"-moz-box-shadow":"0px 0px 12px black",
"-webkit-box-shadow":"0px 0px 12px black",
"z-index":"99"
});
// store all of the old props so it can be animate back
$div.attr("id",opts.useId)
.attr("oldWidth",$(this).width())
.attr("oldHeight",$(this).height())
.attr("oldTop",$(this).offset().top)
.attr("oldLeft",$(this).offset().left)
.attr("oldPadding",$(this).css("padding"));
// put this guy on the page
$("body").prepend($div);
// animate the div outward
$div.animate({
"top":$(this).offset().top-Math.abs($(this).height()-opts.height),
"left":$(this).offset().left-opts.padding,
"height":opts.height,
"padding":opts.padding
},opts.speed);
// loop through each selector and animate it to its css object
for(var eachSelector in opts.selectors){
var selectorObject=opts.selectors[eachSelector];
for(var jquerySelector in selectorObject){
var cssObject=selectorObject[jquerySelector];
$div.find(jquerySelector).animate(cssObject,opts.speed);
}
}
$div.mouseleave(function(){
$("#"+opts.useId).animate({
width:$(this).attr("oldWidth"),
height:$(this).attr("oldHeight"),
top:$(this).attr("oldTop"),
left:$(this).attr("oldLeft"),
padding:$(this).attr("oldPadding")
},0,function(){
$(this).remove();
});
});
});
});
};
$(".productBox").popOut({
height:300,
border:"1px solid #333"
});
});
Thanks in advance!!!

$(this).find(".productImage").animate({...});

Related

Having trouble toggling an animation when clicked on

I am trying to make a div that expands in height when clicked on, and then goes back to its original size when clicked on again. I have tried to use .toggle but whenever I do every div (with the related class) completely vanishes. I posted a code pen below so you can easily view the codes effects.
http://codepen.io/JoshuaHurlburt/pen/JKqAPr
<div>
<div class='box' id='emailVer'>
<h2 id='payText'>PAYMENT</h2>
</div>
<div class='box' id='accCust'>
<h2 id='acText'>ACCOUNT CUSTOMIZATION</h2>
</div>
<div class='box' id='pay'>
<h2 id='evText'>EMAIL VERIFICATION</h2>
</div>
</div>
JS:
var main = function(){
$('.box').click(function() {
$(this).animate({
height: "300px"
},200 );
}
)}
$(document).ready(main);
I decided to leave out the CSS, but I will edit it in if anyone thinks it is important to the solution
There's probably a better solution than this but here is one-
Replace your script file with this
var main = function(){
$('.box').click(function() {
var el = $(this);
if (!el.hasClass('selected')) {
el.animate({
"height": "300px"
}, 200)
el.addClass("selected");
} else {
el.animate({
"height": "75px"
}, 200);
el.removeClass("selected");
}
}
)}
$(document).ready(main);
What you need is a way to track what has already been selected (and animated) and what has not. I chose to add a class (selected) and check to see if the element has that class. If it has not yet been selected, animate to 300px and add the class, else animate back to 75px and remove it.
Try .slideToggle
$( "#clickme" ).click(function() {
$( "#book" ).slideToggle( "slow", function() {
// Animation complete.
});
});
The toggle functions in jQuery toggle the visibility of an element which is why they disappear.
I believe what you are looking for is .toggleClass. See http://api.jquery.com/toggleclass/. You can then create another class with the expanded height properties. Which will be toggled on and off on click.
Adding height to your existing transition property on box will handle the animation.
CSS
.box {
width:300px;
height:75px;
margin:0 auto;
-webkit-transition:box-shadow 1s, height 1s;
transition: box-shadow 1s, height 1s;
}
.expanded {
height: 300px;
}
JS
var main = function(){
$('.box').click(function() {
$(this).toggleClass('expanded');
}
)};
$(document).ready(main);

Run Jquery only when an element is in the viewport

I'm trying to perform the Jquery function below when the element becomes visible in the viewport rather than on the page load. What would I need to change to allow that to happen? I'm using an external JS file to perform the Jquery, so keep that in mind.
Here's a piece of the HTML that is associated with the Jquery function -
<div class="skillbar clearfix " data-percent="70%">
<div class="skillbar-title" style="background: #FF704D;">
<span>Illustrator</span></div>
<div class="skillbar-bar" style="background: #FF704D;"></div>
<div class="skill-bar-percent">70%</div>
</div>
jQuery(document).ready(function(){
jQuery('.skillbar').each(function(){
jQuery(this).find('.skillbar-bar').animate({
width:jQuery(this).attr('data-percent')
},4000);
});
});
I once came across such problem and what I used is waypoints small library.
all you need is to include this library and do:
var waypoint = new Waypoint({
element: document.getElementById('waypoint'),
handler: function(direction) {
console.log('Element is in viewport');
}
})
Using CSS3 transitions instead of jQuery animations might be more performant and simpler. a cheap and nasty way of pushing it out of screen to demonstarate the effect.
There's a couple of things you'll need to do - firstly if you only want the animation to trigger when it's in the viewport then you'll need to check if anything is in the viewport on scroll. Then only update the bars width when it comes into view. If you want the effect to repeat every time it comes into viewport you'll need to set .skillbar-bar's width back to 0 if it's out of the viewport (just add an else statement to the viewport checking if)
I've added a 1000px margin-top and 400px margin-bottom in my example to .skillbar as a cheap and nasty way of demonstrating the effect
(function($){
$(document).ready(function(){
var $els = $('.skillbar'); // Note this must be moved to within event handler if dynamically adding elements - I've placed it for performance reasons
var $window = $(window);
$window.on('scroll', function(){
$els.each(function(){ // Iterate over all skillbars
var $this = $(this);
if($window.scrollTop() > $this.offset().top - $window.height()){ // Check if it's in viewport
$this.find('.skillbar-bar').css({'width' : $this.attr('data-percent')}); // Update the view with percentage
}
});
});
});
}(jQuery));
.skillbar{
margin-top: 1000px;
margin-bottom: 400px;
position: relative
}
.skillbar-bar{
transition: width 4s;
position: absolute;
height: 20px;
}
.skill-bar-percent{
position: absolute;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Scroll down 1000px :)
<div class="skillbar clearfix " data-percent="70%">
<div class="skillbar-title">
<span>Illustrator</span></div>
<div class="skillbar-bar" style="background: #FF704D; width: 20%"></div>
<div class="skill-bar-percent">70%</div>
</div>
This might work for you.
var el = $('.yourElement'),
offset = el.offset(),
scrollTop = $(window).scrollTop();
//Check for scroll position
if ((scrollTop > offset.top)) {
// Code..
}

resize div depending on an image size using jquery

I have an image and a colored div overlay over my image.
I get the image width and height using jquery to set the colored overlay div width and heights.
it works fine.
here is my html :
<div class="image_overlay">
<div class="overlay"></div>
<img src="http://us.123rf.com/400wm/400/400/1xpert/1xpert1101/1xpert110100083/8712640-rainbow-cubes-3d-render-image.jpg" class="image">
</div>
<div class="image_overlay">
<div class="overlay"></div>
<img src="http://4.bp.blogspot.com/-BrLngyC1Bto/UpO-IY1kcNI/AAAAAAAALqA/1bSQRy3G_gU/s1600/Image-b%C3%A9b%C3%A9-facebook-8.jpg" class="image">
</div>
my css
.image_overlay{
position:relative}
.image{
z-index:1;
width:50%;
height:auto;
}
.overlay{
background-color:rgba(13, 181, 30, 0.8);
position:absolute;
z-index:2;
}
and my jquery
$(".image").load(function(){
var image_h=this.height,
image_w=this.width;
$(".overlay").height(image_h);
$(".overlay").width(image_w);
});
now I'm trying when resizing the window that the overlay get the same size of my image, using $(window).on('resize',function()... but I can't find out how to do it...
here is what I tried : http://jsfiddle.net/o4ngj624/
Can anybody help me with this ?
thanks a lot for your help,
$(document).ready(function(){
$(".image").load(function(){
var image_h=this.height,
image_w=this.width;
$(".overlay").height(image_h);
$(".overlay").width(image_w);
});
$(window).trigger('resize');
});
$(window).on('resize',function() {
var image_h=this.height,
image_w=this.width;
$(".overlay").height(image_h);
$(".overlay").width(image_w);
});
here is Jsfiddle to see it in action :
You should just trigger load event of image.
$(document).ready(function () {
$(".image").load(function () {
var image_h = this.height,
image_w = this.width;
//Use prev to find previous overlay
$(this).prev(".overlay").height(image_h).width(image_w);
});
});
$(window).on('resize', function () {
$(".image").trigger('load'); //Trigger load event of image
}).trigger('resize');
DEMO

Jquery/CSS sequential element animation with callback

I am writing a script that will animate a set of jQuery Elements, but I'm running into some issues. Here are my requirements:
Sequential animations
Callback functionality after all animations are complete. Callback can be defined globally
Animation works on floated elements with
Entire solution can be js/jquery/css or a combination
Here's what I've gotten so far: http://jsfiddle.net/fmpeyton/cqAws/
HTML
<div class="block">Im a box</div>
<div class="block">me too</div>
<div class="block">and me!</div>
<div class="block">am I?</div>
<div class="block">yes.</div>
<div class="block">Im a box</div>
<div class="block">me too</div>
<div class="block">and me!</div>
<div class="block">am I?</div>
<div class="block">yes.</div>
<div class="block">Im a box</div>
<div class="block">me too</div>
<div class="block">and me!</div>
<div class="block">am I?</div>
<div class="block">yes.</div>
CSS
.block{
float:left;
width:100px;
background: red;
margin: 0 10px;
padding: 10px;
}
.hiddenForAnimation{ opacity:0; margin-top:-20px; }
JS
$(function(){
$('.block').addClass('hiddenForAnimation').each(function(i){
var delay = i * 200,
animationSpeed = 800;
$(this).delay(delay).animate({opacity: '1', marginTop: '0px'
}, animationSpeed, function(){ if(typeof afterPageAnimation === 'function' && i === $(this).length){ setTimeout(afterPageAnimation, delay + animationSpeed);} $(this).removeClass('hiddenForAnimation').attr('style',''); });
});
});
function afterPageAnimation(){ alert('animation is done!'); }
My issues:
Is there a better way to refactor this JS script to be sequential? Using delay() is effective, but not elegant.
The callback is not being executed directly after the animations
When the last element in a row finishes animating, the first element in the next row starts at the far right, then jumps to the left (I suspect margin-top has something to do with this.)
Thanks!
This works
http://jsfiddle.net/cqAws/12/
Remember: In positioning animations, use position:relative or position:absolute and play with top, left, right, bottom instead of margins.
It's better
EDIT: made it a little better.
new
$(function(){
j=0;
$('.block').each(function(i){
var interv = +(i*800);
var animationSpeed = 800;
$(this).toggleClass('hiddenForAnimation')
.delay(interv)
.animate({opacity: '1', marginTop: '0'},animationSpeed,function(){
j++;
$(this).delay(+(interv+animationSpeed))
.toggleClass('hiddenForAnimation')
.attr('style','');
if(j>=+($('.block').length)) afterPageAnimation();
});
});
});
function afterPageAnimation(){ alert('cool'); }
FIDDLE
For future viewers:
I've solved this by creating a small Jquery plugin found here: https://github.com/fillswitch/Jquery-Sequential-Animations
Hope this helps some other users in the future!

Controlling CSS Float with JQuery

I am writing something similar to the JQuery UI accordion, but vertical. I have it working pretty well with one exception. When you click the third tab, it floats left and shows the required text as expected, but it moves to a position before the second tab. Making the tab order 132 rather than 123. In every other state the numbers are ok.
Any thoughts on making the float stop in the correct order
I am aware of other vertical accordions that could be used but js is one of my weaker areas, I'm doing this more for learning.
I have it saved on a jsfiddle
My Javascript Code
$(document).ready(function(){
$("#1").css("background-color","#191970");
$("#1").css("width", "50px");
$("#1").css("float", "left");
$("#2").css("background-color","#191970");
$("#2").css("width", "50px");
$("#2").css("float", "right");
$("#3").css("background-color","#191970");
$("#3").css("width", "50px");
$("#3").css("float", "right");
$("#boxmain").css("background-color", "#CCC");
$("#boxmain").css("width", "400px");
$("#boxmain").text($("#onet").text());
$('p').hide();
$("#1").click(function() {
$("#2").css("float", "right");
$("#3").css("float", "right");
$("#boxmain").effect("highlight", {color: '#DDD'}, 900);
$("#boxmain").text($("#onet").text());
});
$("#2").click(function() {
$("#2").css("float", "left");
$("#3").css("float", "right");
$("#boxmain").effect("highlight", {color: '#DDD'}, 900);
$("#boxmain").text($("#twot").text());
});
$("#3").click(function() {
$("#3").css("float", "left");
$("#2").css("float", "left");
$("#boxmain").effect("highlight", {color: '#DDD'}, 900);
$("#boxmain").text($("#threet").text());
});
});
I can help you simplify this quite a lot. There's a lot to read, but you can see it working at jsfiddle first if you like. You don't need to swap about the floats, you can just swap about the different containers.
First, some CSS:
.accordion {
height:200px;
float: left;
border:#fff solid 1px;
border-radius: 10px 10px 10px 10px;
color:white;
width: 50px;
background: #191970;
}
.boxMain {
width: 400px;
background: #CCC;
}
Then HTML- notice how I use the accordion class to tidy it up:
<div style="height:200px;width:558px;" id="box">
<div id="1" class="accordion">1</div>
<div id="boxmain" class="accordion boxMain"></div>
<div id="2" class="accordion">2</div>
<div id="3" class="accordion">3</div>
</div>
<p id="onet">Number One Text</p>
<p id="twot">Number Two Text</p>
<p id="threet">Number Three Text</p>
Now the script. I have removed all the CSS statements because it's done with CSS instead. I'll explain the .click() method afterwards.
$(document).ready(function(){
$("#boxmain").text($("#onet").text());
$('p').hide();
$("#1").click(function() {
$("#boxmain").insertAfter(this);
$("#boxmain").effect("highlight", {color: '#DDD'}, 900);
$("#boxmain").text($("#onet").text());
});
$("#2").click(function() {
$("#boxmain").insertAfter(this);
$("#boxmain").effect("highlight", {color: '#DDD'}, 900);
$("#boxmain").text($("#twot").text());
});
$("#3").click(function() {
$("#boxmain").insertAfter(this);
$("#boxmain").effect("highlight", {color: '#DDD'}, 900);
$("#boxmain").text($("#threet").text());
});
});
The click method uses the concept of "this" to refer to the element that click() is running on. In the case of $("#1").click() $(this) refers to #1. Instead of trying to shuffle floats around, you move the #boxmain element around instead.
Your divs are ordered that way in the markup. You won't be able to get the effect you're going for by changing float directions. Instead you can move your boxmain div around. Consider this code instead :
http://jsfiddle.net/Lanny/4snqy/18/

Categories

Resources