How to rollover image with time delay? - javascript

Actually in the products page, we want to reduce the burden on the server to bring the images only after delay of 2 to 3 seconds on mouse over. So If the user hover the cursor we should hit the server after 2 seconds and bring the new image. But the below code is not working as per our expectation.
HTML Tag:
<img class="rollover-images" data-rollover="{bringNewImage()}" src="{bringOldImage()}" />
Javascript:
$('.rollover-images').each(function() {
var newSrc = $(this).data('rollover');
if(newSrc == 0) return;
var timeout, oldSrc;
$(this).hover(function() {
timeout = setTimeout(function() {
oldSrc = $(this).attr('src');
$(this).attr('src', newSrc).stop(true,true).hide().fadeIn(1);
}, 2000);
}, function() {
clearTimeout(timeout);
$(this).attr('src', oldSrc).stop(true,true).hide().fadeIn(1);
});
});

There are several problems with the posted code
You cannot put in a javascript function for an HTML attribute and expect it to be replaced by the function return value. So your HTML should be
<img class="rollover-images" data-rollover="new.png" src="old.png" />
You have a problem with this inside the timeout function. Since you have begun a new function scope, the value of this won't be your img node. So your JS should be
$(this).hover(function () {
var self = this
timeout = setTimeout(function () {
oldSrc = $(self).attr('src');
$(self).attr('src', newSrc).stop(true, true).hide().fadeIn(1);
}, 2000);
}, function () {
clearTimeout(timeout);
$(this).attr('src', oldSrc).stop(true, true).hide().fadeIn(1);
});
Notice that we defined a new variable called self which is used inside the setTimeout call.

Related

JQuery: Onload event on image not working

I am trying to call a function after the image loads completely in DOM.
The image structure is created dynamically on AJAX call success and the image url is also added in success using the result of API call.
Problem:
I want to call a function after the image loads completely in DOM.
To do this I have used JQuery load event.
Function which is called on load.
function carouselHeight() {
$('.home-banner-img-container').each(function() {
var $this = $(this);
var dynamicheight = $(this).parent();
var sectionInnerHeight = $this.innerHeight();
dynamicheight.css({
'height': sectionInnerHeight
});
});
}
I have tried below steps but it didn't worked
$(window).on('load', function() {
carouselHeight();
});
$(window).on('load', 'img.image-preview', function() {
carouselHeight();
});
$(document).on('load', 'img.image-preview', function() {
carouselHeight();
});
The first method $(window).on('load', function() {}) works perfectly on hard reload but on normal reload it is not able to find $('.home-banner-img-container') element which is inside of carouselHeight function.
Please help me to find a solution for this. Thank you.
I have found the solution on stack overflow where I have added the below code in ajax call complete method.
function imageLoaded() {
// function to invoke for loaded image
// decrement the counter
counter--;
if( counter === 0 ) {
// counter is 0 which means the last
// one loaded, so do something else
}
}
var images = $('img');
var counter = images.length; // initialize the counter
images.each(function() {
if( this.complete ) {
imageLoaded.call( this );
} else {
$(this).one('load', imageLoaded);
}
});

Removing class after X seconds?

I'm trying this below code:
$(document).ready(function() {
$("button").hover(
function() {
$(this).addClass("active");
},
function() {
$(this).removeClass("active");
}
);
});
Try this: http://plnkr.co/edit/Xlco44QPWvKEh1jb0gDf?p=preview
var button = $('button');
button.hover(
function() {
button.addClass('active');
setTimeout(function() {
button.removeClass('active');
}, 3000);
},
function() {
button.removeClass('active');
}
);
From what you said in your previous comment below, you tried setTimeout and it didn't work because of the the way you used this. The value of this inside the timeout function wasn't the same as in your outer function, so jQuery didn't match your button element.
Better to define the button once as a variable, and reuse the variable, that use repeated jQuery selectors.
UPDATE: Here's a slightly more sophisticated version that keeps the setTimeout timers from piling up:
$(function() {
var button = $('button');
var timeout = 0;
button.hover(
function() {
button.addClass('active');
timeout = setTimeout(function() {
button.removeClass('active');
timeout = 0;
}, 2000);
},
function() {
button.removeClass('active');
if (timeout) {
clearTimeout(timeout);
timeout = 0;
}
}
);
});
I have created a jQuery extention just for that! This is extremely common in web development:
jQuery.addTempClass.js
$.fn.addTempClass = function(tempClass, duration){
if( !tempClass )
return this;
return this.each(function(){
var $elm = $(this),
timer;
$elm.addClass(tempClass);
// clear any timeout, if was any
clearTimeout( $elm.data('timeout') )
timer = setTimeout(function(){
$elm.removeClass(tempClass).removeData('timeout');
}, duration || 100);
// set the timer on the element
$elm.data('timeout', timer);
});
};
Usage example:
$(document.body).addTempClass('some_class', 2000)
You can include this script as a dependency file for your build system or simply copy-paste this piece of code somewhere in your code, just after jQuery has loaded, so it will be available everywhere afterwards.

How to pass variable asyncronously through different scripts

I can't figure out how to do it.
I have two separate scripts. The first one generates an interval (or a timeout) to run a specified function every x seconds, i.e. reload the page.
The other script contains actions for a button to control (pause/play) this interval.
The pitfall here is that both sides must be asyncronous (both run when the document is loaded).
How could I properly use the interval within the second script?
Here's the jsFiddle: http://jsfiddle.net/hm2d6d6L/4/
And here's the code for a quick view:
var interval;
// main script
(function($){
$(function(){
var reload = function() {
console.log('reloading...');
};
// Create interval here to run reload() every time
});
})(jQuery);
// Another script, available for specific users
(function($){
$(function(){
var $playerButton = $('body').find('button.player'),
$icon = $playerButton.children('i');
buttonAction = function(e){
e.preventDefault();
if ($(this).hasClass('playing')) {
// Pause/clear interval here
$(this).removeClass('playing').addClass('paused');
$icon.removeClass('glyphicon-pause').addClass('glyphicon-play');
}
else {
// Play/recreate interval here
$(this).removeClass('paused').addClass('playing');
$icon.removeClass('glyphicon-play').addClass('glyphicon-pause');
}
},
buttonInit = function() {
$playerButton.on('click', buttonAction);
};
buttonInit();
});
})(jQuery);
You could just create a simple event bus. This is pretty easy to create with jQuery, since you already have it in there:
// somewhere globally accessible (script 1 works fine)
var bus = $({});
// script 1
setInterval(function() {
reload();
bus.trigger('reload');
}, 1000);
// script 2
bus.on('reload', function() {
// there was a reload in script 1, yay!
});
I've found a solution. I'm sure it's not the best one, but it works.
As you pointed out, I eventually needed at least one global variable to act as a join between both scripts, and the use of a closure to overcome asyncronous issues. Note that I manipulate the button within reload, just to remark that sometimes it's not as easy as moving code outside in the global namespace:
Check it out here in jsFiddle: yay! this works!
And here's the code:
var intervalControl;
// main script
(function($){
$(function(){
var $playerButton = $('body').find('button.player'),
reload = function() {
console.log('reloading...');
$playerButton.css('top', parseInt($playerButton.css('top')) + 1);
};
var interval = function(callback) {
var timer,
playing = false;
this.play = function() {
if (! playing) {
timer = setInterval(callback, 2000);
playing = true;
}
};
this.pause = function() {
if (playing) {
clearInterval(timer);
playing = false;
}
};
this.play();
return this;
};
intervalControl = function() {
var timer = interval(reload);
return {
play: function() {
timer.play();
},
pause: function(){
timer.pause();
}
}
}
});
})(jQuery);
// Another script, available for specific users
(function($){
$(function(){
var $playerButton = $('body').find('button.player'),
$icon = $playerButton.children('i'),
interval;
buttonAction = function(e){
e.preventDefault();
if ($(this).hasClass('playing')) {
interval.pause();
$(this).removeClass('playing').addClass('paused');
$icon.removeClass('glyphicon-pause').addClass('glyphicon-play');
}
else {
interval.play();
$(this).removeClass('paused').addClass('playing');
$icon.removeClass('glyphicon-play').addClass('glyphicon-pause');
}
},
buttonInit = function() {
$playerButton.on('click', buttonAction);
interval = intervalControl();
};
buttonInit();
});
})(jQuery);
Any better suggestion is most welcome.

Anonymous function in setTimeout not working

I'm trying to create a delay between two loops of the nivo-slider.
Without the setTimeout everything works just fine (but without delay). So the folloing example works:
$('#slider').nivoSlider({
lastSlide: function(){
$('#slider').data('nivo:vars').stop = true;
// setTimeout(function() {
$('#slider').data('nivo:vars').stop = false;
// }, 2000);
},
});
If I uncomment the setTimeout-lines the slider stops but does not start again? Any ideas why?
Update:
http://jsfiddle.net/kgYNX/
2nd update:
Tried it with a wrapping function, too. The function gets called but if I use setTimeout in the new function it stops working: http://jsfiddle.net/kgYNX/1/
Solved it slightly different:
beforeChange: function(){
$('#slider').data('nivo:vars').stop = true;
var delay = 0;
if ($('#slider').data('nivo:vars').currentSlide == $('#slider').data('nivo:vars').totalSlides - 2) {
delay = 2000;
}
setTimeout(function() {
$('#slider').data('nivo:vars').stop = false;
}, delay);
}
I don't know why "totalSlides - 2", but it works: http://jsfiddle.net/kgYNX/15/
As a variant, you may add custom option to slider vars collection to prevent stop execution on lastSlide handler when slider re-enabled by timeout:
lastSlide: function () {
var dontStop = $('#slider').data('nivo:vars').dontStopOnLast;
if (!dontStop) {
$('#slider').data("nivoslider").stop();
setTimeout(function () {
$('#slider').data("nivoslider").start();
}, 2000);
}
$('#slider').data('nivo:vars').dontStopOnLast = !dontStop;
}

does jQuery stop() work on custom functions?

There are three images that I have made a tooltip for each.
I wanted to show tooltips within timed intervals say for 2 seconds first tooltip shows and for the second interval the 2nd tooltips fades in and so on.
for example it can be done with this function
function cycle(id) {
var nextId = (id == "block1") ? "block2": "block1";
$("#" + id)
.delay(shortIntervalTime)
.fadeIn(500)
.delay(longIntervalTime)
.fadeOut(500, function() {cycle(nextId)});
}
now what i want is to stop the cycle function when moseover action occurs on each of the images and show the corresponding tooltip. And again when the mouse went away again the cycle function fires.
If I understand everthing correctly, than try this code. Tt stops the proccess if you hover the image and continues if you leave the image. The stop() function will work on custom functions if you implement them like the fadeOut(), slideIn(), ... functions of jquery.
$('#' + id)
.fadeIn(500, function () {
var img = $(this).find('img'),
self = $(this),
fadeOut = true;
img.hover(function () {
fadeOut = false;
},
function () {
window.setTimeout(function () {
self.fadeOut(500);
}, 2000);
}
);
window.setTimeout(function () {
if (fadeOut === false) {
return;
}
self.fadeOut(500);
}, 2000);
});​

Categories