Can I slow down this Javascript function? - javascript

I'm new to javascript and jquery, so please forgive my ignorance. I created a webpage where you rollover a text link and an image in another div changes. I used the method from here: http://jsfiddle.net/fWpJz/1/ to create my page and it works well.
Here is the code I'm using:
$(document).ready(function () {
$('.productmenu a').hover(function () {
$('#prodimage img').attr('src', $(this).data('image-src'));
$('.image-src').stop().animate({.attr}, slow);
});
});
I'd like to slow down the transition from one image to another on mouse over, so that the image doesn't flip as abruptly.
I used this tutorial (http://bavotasan.com/2009/creating-a-jquery-mouseover-fade-effect/) to create an effect that I like, but don't know how to combine it with the image changes based on a link hover. Here is the code from the jsfiddle.net:
$(document).ready(function () {
$('.menu a').hover(function () {
$('#container img').attr('src', $(this).data('image-src'));
});
});
Can anyone point me to the correct piece of code and how I can add it into my javascript? I've never used jquery before, so I don't know how to add an animate function.
Thank you!!

What if I told you you didn't have to use jQuery.animate at all to achieve the effect you want? Use CSS3 transitions! Here's a forked version of your fiddle showing how to accomplish what you're looking to do (I think) (I've put the html/css/js at the bottom of this post as well).
When the DOM content has loaded, the alignItems function makes sure that all images stay in the same place on the page. The script keeps track of the current image being displayed. Every time a different link is moused over, the image being displayed gets updated, such that the old current image gets its opacity set to 0 and the new current image gets its opacity set to 1. Then CSS transitions can be used to animate the opacity, which blows away $.fn.animate, but will only work on modern browsers (see caniuse...motherf***ing IE -_- ). Code below:
html
<div class="menu">
link 1
link 2
link 3
link 4
link 5
</div>
<div id="container">
<img id="1" src="http://farm7.staticflickr.com/6092/6330704947_dd7e1b453c_t.jpg" />
<img id="2" src="http://farm1.staticflickr.com/13/15463218_8651d51b21_t.jpg"/>
<img id="3" src="http://farm3.staticflickr.com/2570/4220856234_029e5b8348_t.jpg" />
<img id="4" src="http://farm4.staticflickr.com/3036/2975303180_86c4858b2b_t.jpg" />
<img id="5" src="http://farm7.staticflickr.com/6216/6240217938_aeed84634a_t.jpg" />
</div>
css
.menu a {
padding: 2px 4px;
color: #555;
text-decoration: none;
}
.menu a:hover {
color: #ddd;
background: #333;
}
#container {
margin-top: 10px;
}
#container img {
margin: 4px;
padding: 4px;
border: 1px dashed #aaa;
opacity: 0;
-webkit-transition: opacity 500ms ease-in;
-moz-transition: opacity 500ms ease-in;
transition: opacity 500ms ease-in;
}
javascript
$(document).ready(function () {
alignImages();
var currentImgId = 0;
$('.menu a').hover(function () {
var oldImgId = currentImgId;
currentImgId = this.dataset.imageId;
$(document.getElementById(oldImgId)).css('opacity', 0);
$(document.getElementById(currentImgId)).css('opacity', 1.0);
});
});
function alignImages() {
var $images = $('#container img');
var position = $images.eq(0).position();
$images.each(function() {
this.style.position = 'absolute';
this.left = position.left;
this.top = position.top;
});
}

Below is one of the implementations by using setTimeout
var count = 0;
$(document).ready(function () {
$('.menu a').hover(function () {
var self = this;
var innerCount = ++count;
setTimeout(function(){
if(innerCount == count) //If mouse move out within 1 second, will not show new image
{
$('#container img').attr('src', $(self).data('image-src'));
}
}, 1000); //1 second delay
});
});

Try this:
your HTML should be like this:
<div id="container" style="display:none;">
<img src="">
</div>
and in your script :
$('.menu a').hover(function () {
$('#container').hide();
$('#container').fadeIn().animate({ opacity: 1, top: "-10px" }, 'slow');
$('#container img').attr('src', $(this).data('image-src'));
});
Effect should be nice in transition See: JSFiddle

Related

How to make two elements appear and disappear on a top of each other in an infinite loop

I trying to make header one disappear, then header two appear and disappear and header one appear in a loop. The problem with my code is, that header two appears only for very short amount of time and empty screen follows for at least 2-3 seconds before header one appears.
JS:
var h1 = $('.header_one');
var h2 = $('.header_two');
setInterval(function(){
h1.fadeOut(1000);
h2.fadeIn(1000);
h2.fadeOut(2000, function() { h1.fadeIn(); });
}, 4000);
HTML:
<h1 class="header_one"> HEADER ONE </h1>
<h2 class="header_two"> HEADER TWO </h2>
CSS:
h1, h2 {
z-index: 10;
position: relative;
}
h2 {display: none;}
There is also a problem: when header two disappears, my two links underneath h1 and h2, that are set to position: relative; move to the top of the page.
Here's one way to do it: jsfiddle
$("#box1").hide();
function animate() {
$("#box2").fadeOut(1000, function() {
$("#box1").fadeIn(1000, function() {
$("#box1").fadeOut(1000, function() {
$("#box2").fadeIn(1000, animate);
});
});
});
}
animate();
div {
position: absolute;
left: 20px;
top: 20px;
background: red;
width: 50px;
height: 50px;
}
div:nth-child(2) {
left: 30px;
top: 30px;
background: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="box1"></div>
<div id="box2"></div>
The reason why your links are moving up when the headers disappear is because the fadeIn and fadeOut are manipulating the display property which removes it from the flow of the document. Only the visibility property would retain the element's position and reserve the space for it.
Assuming that your 2 headers look the same in terms of styling, why not use just one and change the text inside it while animating the color/transparency?
But if you really want to fire them in sequence given your code then you need to do what you did on the last line, where one is a callback when the other finishes; however, this won't fix your links moving up problem.
This is a really nasty/bad way of doing it, but it works...
setInterval(function(){
$('h1').fadeOut(function(){
$('h2').fadeIn();
});
}, 4000);
setInterval(function(){
$('h2').fadeOut(function(){
$('h1').fadeIn();
});
}, 8000);
this is my option to do a loop with jquery animate:
https://jsfiddle.net/vbw8jLko/
var h1 = $('.header_one');
var h2 = $('.header_two');
function loop(){
console.log('llop');
$( ".header_one" ).stop().css('opacity', 0).show().animate({opacity:1}, 700).delay(700).animate({
opacity: 0
}, 1000, function(){
$(this).hide();
$( ".header_two" ).stop().css('opacity', 0).show().delay(100).animate({
opacity: 1
}, 1000).delay(700).animate({opacity:0}, 1000, function(){
$(this).hide(); loop()});
});
}
loop();
Expect like it :)

Changing background image - javascript

I would like to change a background image with JavaScript.
JS:
<head>
<script type="text/javascript">
// Ta funkcja odpowiedzialna jest odpowiedzialna za zmiane obrazow w tle
$(window).load(function(){
var i = 0;
var images = ['images/1.jpg','images/2.jpg','images/3.jpg','images/4.jpg','images/5.jpg'];
var image = $('#slideit');
image.css('background-image', 'url(images/1.jpg)');
image.css('background-size', 'cover');
setInterval(function(){
image.css('background-image', 'url(' + images [i++] +')');
// image.fadeOut(1500, function (){
// image.fadeIn(1000);
// })
if(i == images.length) i = 0;
}, 6000);
});
</script>
</head>
HTML:
<body id="slideit" style="width:100%;height:100%;">
The problem is in making the images change smoothly. The commented out code makes everything in the website fade in and fade out except the background. Why is this happening? This code works but does not change the image smoothly. How can I fade the images in and out?
Unfortunately CSS does not support the animation (via transition) of background images. Why? Actually, I'm not sure why. But it's enough to know they don't. Javascript works directly by extending CSS functionality. In short, what you want to do can't be done with Javascript without writing a very convoluted piece of code designed at hacking its functionality.
There is an easy work around using jQuery, however, which will actually make your source less complex too. Make the body relative, add each individual background image to the bottom of your source (to make them load after everything else) inside a named wrapper. Let's go with #backgrounds.
<style>
body{
height:100%;
position:relative
}
#backgrounds img{
position:absolute;
z-index:1; // this is important
top:0;
left:0;
width:100%;
height:100%;
opacity:0;
display:none;
}
#wrapper{
position:relative;
z-index:3; // again, this is important
}
</style>
We set the z-index of the wrapper to be higher than that of the images so that our content is in front of them, thus giving the illusion the images are background images. Change position:absolute to position:fixed if you want a background-attachment:fixed effect. I'm assuming you want their widths and heights to be that of the viewport; change them to whatever if not. We set the images to display:none to stop them all loading when the page loads. Yuck!
<div id="wrapper">
all of your page are belong to us...
</div>
<div id="backgrounds">
<img src="background/one.jpg" alt="">
<img src="background/two.jpg" alt="">
<img src="background/three.jpg" alt="">
</div>
And then simply cycle through each image using a counter based on the number of images (so you can easily cut and paste more images in later without any effort):
$(function(){
var total = $('#backgrounds img').length;
var counter = 1;
function cycle(){
// Makes old backgrounds appear beneath new ones
$('#backgrounds img').css('z-index','1')
// Set it to display and opacity 0 so we get the effect
$('#backgrounds img:nth-child('+counter+')').css({'opacity':'0','display':'block','z-index':'2'})
// Fade the background in
$('#backgrounds img:nth-child('+counter+')').animate({'opacity':'1'},1500)
// increase the counter
counter++
// make sure we're working within the quantity of images we have
if( counter > total ){ counter = 1 }
}
cycle();
setInterval(function(){cycle()},6000);
})
Try
$(function() {
$.fx.interval = 3000;
(function cycleBgImage(elem, bgimg) {
elem.css("backgroundImage", bgimg).delay(3000, "fx")
.fadeTo(3000, 1, "linear", function() {
$(this).fadeTo(3000, 0, "linear", function() {
var img = $(this).css("backgroundImage").split(",")
, bgimg = img.concat(img[0]).splice(1).join(",");
cycleBgImage(elem, bgimg);
});
});
}($("#slideit")));
});
#slideit {
width: 100%;
height: 100%;
display: block;
opacity: 0.0;
background-color: #000;
background-image: url("http://lorempixel.com/400/400/cats/?1")
, url("http://lorempixel.com/400/400/animals/?2")
, url("http://lorempixel.com/400/400/nature/?3")
, url("http://lorempixel.com/400/400/technics/?4")
, url("http://lorempixel.com/400/400/city/?5");
background-size: cover, 0px, 0px, 0px;
-webkit-transition: background-image 3000ms linear;
-moz-transition: background-image 3000ms linear;
-ms-transition: background-image 3000ms linear;
-o-transition: background-image 3000ms linear;
transition: background-image 3000ms linear;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<body id="slideit"></body>

Adding Flag to javascript (hasClass)

So I have images where when you click they expand (via css). However, I also want it so that when you click, the image will be pushed to the top of the page. From what I've heard is that if I use the toggleClass function then I need to have a flag before I initiate the animation, however, I can't seem to get it to function right.
$("img").on("click", function (){
$(this).toggleClass("selected");
if ($("img").hasClass("selected")) {
found = true;
}
var timeout = setTimeout(function () {
$('html,body').animate({
scrollTop: $('.selected').offset().top - 60
}, 100);
}, 5);
});
You should consider using CSS3 transition rather than monitoring using timers. You set transition to transition the top property. Then have the selected class alter the top by toggling it. The change will cause the animation to kick in. See this example:
HTML:
<div class="bar">weee!</div>
CSS:
.bar{
width: 100px;
height: 100px;
background: red;
position: relative;
transition: top 1s ease 0;
top: 100px;
}
.bar.selected{
top : 0px;
}
JS:
$('.bar').on('click',function(){
$(this).toggleClass('selected');
});

Create smooth transition of block elements when removing sibling elements from DOM

I have a container that is working similar to notifications in mac os - elements are added to the queue and removed after a certain timeout. This works great but has one jarring visual side effect.
When they are removed from the DOM there is a jagged update to the UI as the next element in the stack fills the void created by the previous element. I would like the elements below in the stack to move up into that space smoothly, ideally with css3 but adding a transition: all 0.5s ease-in-out to the .notice class had no effect on the object when its sibling was remove.
Minimal JS interpertation :
$('#add').click(function(e) {
e.preventDefault();
$('#container').append('<p class="notice">Notice #</p>');
});
$('body').on('click','p.notice', function(e) {
$(this).fadeOut();
});
Better yet fiddle here :
http://jsfiddle.net/kMxqj/
I'm using a MVC framework to data-bind these objects so some native css / jQuery is preferred over a Jq plugin.
This should remove the clicked element with a fade out effect and then move everything below up smoothly. This will work for any notice div in the stack regardless of it position within the stack.
Try:
$('body').on('click','p.notice', function(e) {
$(this).fadeOut(500,function(){
$(this).css({"visibility":"hidden",display:'block'}).slideUp();
});
});
Fiddle here
Update August 7th, 2018:
As asked by one of the users about using pure JS to do the slideUp functionality, I've put together a quick demo using requestAnimationFrame to animate the height of an element. Fiddle can be found here.
jQuery's Animate() method is a great tool to learn because not only can you fade your objects in and out, but you can move them around, all at the same time.
The CSS:
.notice {
position:relative;
top:20px;
width: 100%;
height: 50px;
background-color: #ccc;
opacity:0;
}
The jQuery:
$('#add').click(function(e) {
e.preventDefault();
$('#container').append('<p class="notice">Notice #</p>');
$('.notice').animate({opacity: 1, top:0}, 1000);
});
$('body').on('click','p.notice', function(e) {
$(this).fadeOut();
});
And my jsFiddle demo
A simple way of doing this would be to animate the height and margin properties - http://jsfiddle.net/kMxqj/14/
$('#add').click(function(e) {
e.preventDefault();
$('#container').append('<p class="notice">Notice #</p>');
});
$('body').on('click','p.notice', function(e) {
$(this).animate({'height':0,'margin':'0'});
$(this).fadeOut();
});
This will animate the height and margins to 0, while also fading out the object which results in a smooth transition. Also adding overflow hidden to your notice box so any content inside is covered as the animation happens.
How about this fiddle
CSS
.notice {
width: 0;
height: 0;
background-color: #ccc;
}
JS
$('#add').click(function(e) {
e.preventDefault();
$('#container').append('<p class="notice">Notice #</p>');
$('#container p.notice:last-child').animate({
width: 100%,
height: 50px
});
});
$('body').on('click','p.notice', function(e) {
$(this).fadeOut();
});
Tweak the values as needbe, but something like this should accomplish what you'd like - it sounds like animate() might be what you want though
No JQuery:
Preferable way is with max-width:
HTML
<div id="wrapper">
<div class="myspan">
child
</div>
<div id="removable" class="myspan">
removable child
</div>
<div class="myspan">
child
</div>
<div class="">
child
</div>
</div>
CSS
.myspan {
display: inline-block;
font-size: 30px;
display: inline-block;
max-width: 200px;
transition: all 1s;
overflow: hidden;
}
.myspan:hover {
max-width: 0;
}

grow/shrink image gallery with jquery WITHOUT affecting the layout

I got an image gallery organized as an <ul>. all images are in <li> elements and when I move my mouse over one of those pictures, it should grow to give the user a visual feedback. thing is, when I just change the size of the image using animate(), the other pictures will be pushed to the side as the resized image uses more space.
therefore I went with cloning the image element, float it right over the original image and then calling animate. this comes with the problem that onMouseOut() is called as soon as the cloned images pops up. so I need a nested hover() function and this is where things got complicated.
I got two errors and I can't find out whats causing them. the first one is, that animate() won't let the cloned image grow beyond the right border of its original, the second is, that I get weird grow/shrink behavior, when moving my mouse quickly over the gallery.
html:
<ul id="gallery1" class="gallery_container">
<li class="frame">
<img src="pic1.jpg" class="picture" /></li><li class="frame">
<img src="pic2.jpg" class="picture" /></li><li class="frame">
<img src="pic3.jpg" class="picture" /></li>
</ul>
css:
.picture
{
height: 200px;
border: 0px;
margin: 0px;
padding: 0px;
}
.frame
{
display: inline-block;
position: relative;
margin: 0px;
margin-right:8px;
padding: 0px;
}
.frame a
{
padding: 0px;
margin: 0px;
}
.gallery_container
{
height: 200px;
width: 150%;
position: relative;
top: 4px;
padding: 0px;
margin: 0px;
}
and finally the code that is giving me those headaches:
$(document).ready(function()
{
var zooming = false;
var zoom = 4;
var speed_zoom = 100;
$('.gallery_container li a').hover(function(element)
{
// disable zooming to prevent unwanted behavior
if(zooming) return;
zooming = true;
$(this).after( $(this).clone(false) );
$(this).next().attr('id', 'focus_frame');
},
function(element) // when the new element pops up, onmouseout is triggered, since the focus_frame is in front of the image
{
$(this).next().hover(function(element)
{
// we need to re-position the element in the dom-tree, since it needs to grow out of a container with overflow: hidden
$('#focus_frame img').animate({'left' : zoom * -1, 'top' : zoom * -1, 'height' : 200+(zoom*2), 'width' : $('#focus_frame img').outerWidth() + (zoom*2)}, speed_zoom);
},
function(element)
{
$(this).remove();
zooming = false;
});
});
});
var $doc=$(document.body)
$doc.on({
"mouseenter" : function (e) {
$doc.find("> .gallery_clone").remove();
var $i=$(this).parent();
$i.pos = $i.offset();
$i.clone()
.addClass("gallery_clone "+$i.parent().parent().attr("class"))
.css({
top:(Math.round($i.pos.top)-3)+"px"
,left:(Math.round($i.pos.left)-3)+"px"
,width:$i.width()
}).appendTo($doc);
}
},
" ul > li > img"
).on ({
"mouseleave" : function (e) {
$(this).remove();
},"> .gallery_clone");
in css .gallery_clone is position:absolute
then i animate .gallery_clone:hover through css but you can do it in the jquery as well i guess, adding a mouseenter event on .gallery_clone
edit : i've literally copy/pasted from my script so you'll have to adapt this code to your html
nb: give css anim a go, it's worth it even if older ie will not animate; (i also made lightbox effect almost pure css for that same gallery - will publish later, not ready for plugin release just now sorry)
nb2: that part "+$i.parent().parent().attr("class") is because in the cms they can chose gallery background color so adding that class forward the background color & other gallery style to the clone (ie you should not need it)

Categories

Resources