I can't run clearInterval for my functions. I use them to scroll the window by firing setInterval with function that fires scrollLeft. The code:
function scrollSpan() {
$('nav#scrolling').children().css('width',config.windowWidth/10+'px');
var inter;
$('nav#scrolling').children('span').hover(function() {
var value;
if($(this).is('.scrollLeft')) {
value = '-=50'
} else {
value = '+=50'
}
inter = setInterval(function() {
$('body, html').animate({
scrollLeft: value
}, 50);
},0)
})
$('nav#scrolling').children('span').mouseleave(function() {
clearInterval(inter)
})
}
Problem is, when mouseleave is triggered, interval doesn't stop.
Fiddle: http://jsfiddle.net/FpX4M/
You are using hover where you should be using mouseenter. When only one handler is passed to hover that handler is called both on enter and leave. So your hover is called twice (once entering and once leaving) but your mouseleave is only called once. This is why even though one interval is cleared, the other remains.
See the documentation, in particular the signature added in v1.4 which takes only a single handler (scrolldown).
EDIT: Jsfiddles with proof:
http://jsfiddle.net/FpX4M/1/
Open your console and see that the handlers trigger twice and that interval continues.
http://jsfiddle.net/FpX4M/2/
In the console you will now see only one firing of the handler and then the intervals stop on leave.
Your whole scope is a little wonky. Try something like this:
var inter;
function scrollSpan() {
$('nav#scrolling').children().css('width',config.windowWidth/10+'px');
}
$('nav#scrolling').children('span').hover(function() {
var value;
if($(this).is('.scrollLeft')) {
value = '-=50'
} else {
value = '+=50'
}
inter = setInterval(function() {
$('body, html').animate({
scrollLeft: value
}, 50);
},0)
});
$('nav#scrolling').children('span').mouseleave(function() {
clearInterval(inter)
});
You need to make sure the inter variable is accessible outside of the function. Also, generally, state functions shouldn't be assigned within functions unless you're changing them rapidly - and it doesn't look like you're detaching them anywhere. The only things that need to be in the function are things that will be repeated. Maybe add a clearInterval(inter); right before your inter = setInterval... to make sure no old intervals persist.
Related
I've tried a few different ways except the right one.
Trying this:
setTimeout( function() {
$('.historyTextBoxes p')
.bind('showText', function(e) {
$(this).fadeIn(800, function(){
$(this).next().length && $(this).next().trigger("showText");
});
}).eq(0).trigger('showText');
}, 4000);
Will wait for 4 seconds, then fade each paragraph in, one after another at the speed of .800 miliseconds.
What I want to do is fade a paragraph in at .800 ms, then wait for 4 seconds before the next paragraph fades in.
The basic set-up of:
$('.historyTextBoxes p')
.bind('showText', function(e) {
$(this).fadeIn(800, function(){
$(this).next().length && $(this).next().trigger("showText");
alert('pause here');
});
}).eq(0).trigger('showText');
works but I've yet to hit the right syntax to make it pause where the alert is.
I tried throwing a call to a function but I don't need to run anything except just to wait.
So in pseudo code, I'm trying to define something like:
function wait() {
pause(for 4 seconds);
}
Then I could just call that function instead of the alert above. My issues with setTimeout has been 'having' to define a function but I'm over thinking something.
Using setTimeout was correct, but you applied it in the wrong place.
$('.historyTextBoxes p').bind('showText',function(e) {
$(this).fadeIn(800,function(){
// this is the callback after the fadein
// here we want to wait (use a timeout)
var next = $(this).next();
if (next.length)
setTimeout(function() {
// before the next text is shown
next.trigger("showText");
}, 4000);
})
}).eq(0).trigger('showText');
This should do it:
function showAll() {
var p = $('.historyTextBoxes p').get(); // array of elements
(function loop() {
if (p.length) {
var el = p.shift();
$(el).fadeIn(800).delay(4000).promise().done(loop);
}
})();
}
demo at http://jsfiddle.net/4dNr3/2/
Note that this uses no explicit timers at all, and nor does it use any events to trigger the next phase - it relies on the animation queue for all timing. Note that it's not generally a good idea to mix timers and animation unless you can guarantee that they're interleaved rather than running in parallel. In this case that's OK, though.
I have written your basic jQuery infinite scroll function. Expected behavior is consistent with the infinite scroll design pattern.
Upon completion of the ajax server call, I am rebinding the scroll event.
Everything works as expected for the first ajax call, however the scroll event is not being rebound for some reason. Adding in console data to debug the function shows that the code is executed through the end of setScrollingAction(), yet the scroll event does not take.
What am I missing?
// Function to make the ajax call, append the results and rebind the scroll event
function loadContent(opts) {
$(opts.scrollTarget).unbind('scroll');
$(opts.loaderObject).show();
$.get($(opts.gridObject).attr('data-link'), function(data) {
var $data = $(data);
$(opts.gridObject).append($data.find(opts.appendObject));
$(opts.loaderObject).hide();
$(opts.gridObject).attr('data-link', $data.find(opts.gridObject).attr('data-link'));
setScrollingAction(opts);
});
};
// Function to set the loading action to the scroll event
function setScrollingAction(opts) {
$(opts.scrollTarget).bind("scroll", function(event) {
if (inLoadingRange(opts)) { loadContent(opts); }
});
};
// Function to determine height from bottom of page
function inLoadingRange(opts) {
var target = opts.scrollTarget;
return ($(target).scrollTop()+opts.heightOffset >= $(document).height() - $(target).height());
};
// Fire it up
$(document).ready(function(){
opts = {
'scrollTarget': $(window),
'loaderObject': "#loading",
'gridObject' : '#tileGrid',
'appendObject': '.newItem',
'heightOffset': 10
};
setScrollingAction(opts);
});
Turns out it was a conflict with the prettyLoader plugin.
If you look through prettyLoader.js you will find the following function:
$.prettyLoader.hide = function() {
$(document).unbind('click', $.prettyLoader.positionLoader);
$(document).unbind('mousemove', $.prettyLoader.positionLoader);
$(window).unbind('scroll');
$('.prettyLoader').fadeOut(settings.animation_speed, function() { $(this).remove(); });
};
All scroll event assignments are being unbound on the third line of the function. Commenting out this line solved the problem, and did not have a noticeable effect of the loading image.
$.prettyLoader.hide = function() {
$(document).unbind('click', $.prettyLoader.positionLoader);
$(document).unbind('mousemove', $.prettyLoader.positionLoader);
//$(window).unbind('scroll');
$('.prettyLoader').fadeOut(settings.animation_speed, function() { $(this).remove(); });
};
I have a function which loops through rows in a table so that only one is shown at any given time.
I want to expand on this so that when I hover over the table, it shows all the rows, and then when I move away, it resumes showing one row at a time.
The Problem I have is that on hovering, the first function keeps going, is there a way to 'pause' the function. I've looked at various examples using ClearInterval(),but can't match them to my script.
//Calling The function that loops through the rows
function hideShow(time)
{
setInterval('showRows()',time);
};
//Set the time between each 'loop' and start looping
$(document).ready(function()
{
hideShow(2000);
}
);
//The hover function to show / hide all the rows
$(document).ready(function()
{
$('#dbTable1 tr').hover(function()
{
$('.Group td').removeClass('RoundBottom');
$('.Group').show();
},
function()
{
$('.Group td').addClass('RoundBottom');
$('.Group').hide();
}
);
}
);
Can anyone show me please how I can combine the two?
You need to keep track of the timer ID when you call setInterval:
var timerID;
function hideShow(time){
timerID = setInterval(showRows, time);
}
Then later on when you want to stop the repetition, call clearInterval and pass in that ID:
// ...
$('.Group td').removeClass('RoundBottom');
$('.Group').show();
clearInterval(timerID);
},
function()
{
hideShow(2000);
$('.Group td').addClass('RoundBottom');
// ...
You could just check the hovering state before doing anything else, like this:
function showRows() {
if (isHovering) {
return;
}
// ...
}
The isHovering variable is just a boolean with current hovering state, that could be set by your callback function.
With the above approach, you can set your timer only once and forget about it.
I have a link:
Here's my link
This is not a normal clickable link, it's coded in jQuery like this:
$("#link").hover(function(e) {
e.preventDefault();
$("#tv").stop().animate({marginLeft: "50px"});
$("#tv img)").animate({opacity: 1});
})
So after hovering unclickable link there's change of #tv's margin and opacity.
Is there any way of making this work only after the user hovers the link area with pointer for more than two seconds?
Because now everything happens in real time.
I know there's delay(), but it doesn't work because it just delays the animation and in this case I don't want any action if the pointer is over for less than two seconds.
Possible without a loop?
What you're after is called hoverIntent.
var animateTimeout;
$("#link").hover(function() {
if (animateTimeout != null) {
clearTimeout(animateTimeout);
}
animateTimeout = setTimeout(animate, 2000);
}, function() {
clearTimeout(animateTimeout);
});
function animate() {
//do animation
}
You just need a setTimeout() to delay the code, along with a clearTimeout() to clear it if the user leaves the link within 2 seconds.
Example: http://jsfiddle.net/mNWEq/2/
$("#link").hover(function(e) {
e.preventDefault();
$.data(this).timeout = setTimeout(function() {
$("#tv").stop().animate({marginLeft: "50px"});
$("#tv img)").animate({opacity: 1});
}, 2000);
}, function(e) {
clearTimeout($.data(this,'timeout'));
});
I am trying to delay the default event or events in a jQuery script. The context is that I want to display a message to users when they perform certain actions (click primarily) for a few seconds before the default action fires.
Pseudo-code:
- User clicks link/button/element
- User gets a popup message stating 'You are leaving site'
- Message remains on screen for X milliseconds
- Default action (can be other than href link too) fires
So far, my attempts look like this:
$(document).ready(function() {
var orgE = $("a").click();
$("a").click(function(event) {
var orgEvent = event;
event.preventDefault();
// Do stuff
doStuff(this);
setTimeout(function() {
// Hide message
hideMessage();
$(this).trigger(orgEvent);
}, 1000);
});
});
Of course, this doesn't work as expected, but may show what I'm trying to do.
I am unable to use plugins as ths is a hosted environment with no online access.
Any ideas?
I would probably do something like this.
$("a").click(function(event) {
event.preventDefault();
doStuff(this);
var url = $(this).attr("href");
setTimeout(function() {
hideMessage();
window.location = url;
}, 1000);
});
I'm not sure if url can be seen from inside the timed function. If not, you may need to declare it outside the click handler.
Edit: If you need to trigger the event from the timed function, you could use something similar to what karim79 suggested, although I'd make a few changes.
$(document).ready(function() {
var slept = false;
$("a").click(function(event) {
if(!slept) {
event.preventDefault();
doStuff(this);
var $element = $(this);
// allows us to access this object from inside the function
setTimeout(function() {
hideMessage();
slept = true;
$element.click(); //triggers the click event with slept = true
}, 1000);
// if we triggered the click event here, it would loop through
// this function recursively until slept was false. we don't want that.
} else {
slept = false; //re-initialize
}
});
});
Edit: After some testing and research, I'm not sure that it's actually possible to trigger the original click event of an <a> element. It appears to be possible for any element other than <a>.
Something like this should do the trick. Add a new class (presumably with a more sensible name than the one I've chosen) to all the links you want to be affected. Remove that class when you've shown your popup, so when you call .click() again your code will no longer run, and the default behavior will occur.
$("a").addClass("fancy-schmancy-popup-thing-not-yet-shown").click(function() {
if ($(this).hasClass("fancy-schmancy-popup-thing-not-yet-shown"))
return true;
doStuff();
$(this).removeClass("fancy-schmancy-popup-thing-not-yet-shown");
var link = this;
setTimeout(function() {
hideMessage();
$(link).click().addClass("fancy-schmancy-popup-thing-not-yet-shown";
}, 1000);
return false;
});
Probably the best way to do this is to use unbind. Something like:
$(document).ready(function() {
$("a").click(function(event) {
event.preventDefault();
// Do stuff
this.unbind(event).click();
});
})
This might work:
$(document).ready(function() {
$("a").click(function(event) {
event.preventDefault();
doStuff(this);
setTimeout(function() {
hideMessage();
$(this).click();
}, 1000);
});
});
Note: totally untested