Is there a beforeScroll event in jQuery? Or can this type of event be replicated at all?
We have a scenario where we need perform an event before a div with overflow:scroll has been scrolled. The problem with using the .scroll event is that this is raised after the div has been scrolled rather than before.
No, there's no such event. The scroll event cannot be cancelled (for obvious reasons) and I would speculate that it fires after the action so that the scrollTop and scrollLeft properties are accurate when accessed.
Possible workarounds might be to capture the mousewheel/DOMMouseScroll events and the keydown events for page up, page down, up, down, etc. keys. There's no 100% method, though - you'll never be able to stop the user from interacting with the browser's scrollbar components. The only true solution there is to roll your own scrollbars.
If you're just looking to find the amount the user scrolled, you could set a timer to store the current scrollLeft/scrollTop in a variable and then check them vs the new values in the scroll event.
I solved this in a crude way that turned out to be surprisingly un-laggy:
I update the position myself after checking that the position is within the range that I want, using position=fixed, and alter the top value.
Related
I have a Javascript function called updatescreen() that performs various actions on page elements.
I call updatescreen() on page load, page scroll, touchmove, orientation and resize. Basically, any time the user is moving things around, I need to update elements to make the page look and function correctly.
Not every trigger actually modifies a page element, but I have to do some checking.
Everything works well, until I start scrolling (or flicking on an iPhone) very quickly. One trigger that happens is that I need to change the position of an element's "top" value (CSS). I have tried this with jQuery "animate" as well as just "css".
If I scroll slowly enough, everything is fine. If I scroll too fast, the script doesn't seem to keep up with my CSS/animation changes, and it ignores the last few, leaving the element in the wrong position. At least, this is what I think is happening.
Is it correct that firing different CSS values at the same element, too quickly, would cause the last ones to be ignored? Are there rules with regards to how jQuery handles this?
Any suggestions on how I could improve this entire workflow?
Thanks!
I'm facing an issue. For a project I'm doing I'm detecting the scrollwheel position and based on that I'm navigating to the next slide or not. A problem is, however, that some Mac users use "natural scroll" - inverting their scrolling on pages. This means that, for those users, I should use scroll in the other direction as trigger.
My question is; is there a way to detect in what direction the user is used to scroll? My initial idea was to track scrolling and see how scrollTop and scrollwheel relate to each other (i.e., I record mousewheel events and see which direction the page scrolls as a result). That, however, requires the user to scroll before I know what to do. Which doesn't work, as users first need to trigger a slide change.
I'm at a loss. All help is appreciated.
There's actually an easy answer, as long the Mac users are using Safari--
function myWheelEventHandler(event) {
var deltaY = -event.wheelDeltaY;
if (event.webkitDirectionInvertedFromDevice) deltaY = -deltaY;
// use value for something
}
In this example, the value of deltaY will be positive when the user rolls the mouse wheel away from them (or the trackpad equivalent), and negative otherwise, regardless of the system-wide "natural" scroll setting.
In other words, if the webkitDirectionInvertedFromDevice property is present and has the value true, then you can be sure "natural" scrolling is enabled. It even updates if the setting changes while your script is running. The property is available for wheel events only (not scroll events).
If the property is not present, or is present but has the value "false" (which will always be the case in Chrome, due to a bug), then unfortunately you don't know if the scroll direction is reversed or not.
Your idea of testing to see how the page moves on wheel events may be the most robust solution. You could create an invisible (empty) div in front of your slideshow, set to overflow:scroll, with a taller empty div inside it. The first time you receive a wheel event on this div, you could then work out the scroll direction and trigger the appropriate slide change.
How can I keep the browser from scrolling, or how can I make the browser continually scroll to a fixed posistion?
I am working on a library for the Nintendo 3DS browser. I made the page fit perfectly within the browser, but the up arrow makes it scroll because the bottom screen is the only window recognized as the visible area.
I want to make it so the div #bottomScreen is the only thing in the bottom screen, and disabling scrolling is the only thing I can think that would work.
I have figured out how to scroll it to a said position via
document.body.scrollTop = 220;
How can I make it continually go to this position?
Making a repeating timer with setTimeout and putting the above code in it won't work. I believe it is because this only works prior to the page loading.
Any advice on how to enforce it?
It should work even after page load. Here's the code, although i'm not sure what the intent of the code is, might be annoying to the user.
setInterval( function(){ document.body.scrollTop = 200 }, 500 ); // set your time
A more elegant solution would be to disable scrolling when that method is called (to scroll to the position of 220 from top or whatever), and re-enable it whenever the appropriate action has been taken by the user etc... jQuery example:
$('body').css('overflow', 'hidden'); // removes scrollbars entirely
$('body').css('overflow', 'auto'); // re-enable scrolling
Otherwise use setInterval() with a very short interval like 10ms to repeatedly fire your scroll function. If you are going to do this it would be wise to add some logic to see if the window is already scrolled to approximately the right position (allow for +/- 10px or something) so it isn't extremely jarring for the user.
The best way I've seen on some sites (like twitter I think or facebook when an image pops up) which is to set the overflow property to hidden on the body element. This prevents any scrolling so all you need to worry about is the position of content when you do that.
I guess you would need to wrap the content in some sort of container element and when you change the overflow of the body element you also set the y-coordinate of the container to reveal the specific area of the page being looked at.
This is by far the best thing I have seen to achieve that effect because it doesn't require timers etc.
You could add a event listener for the scroll event, and then set the position then.
So. I'm making a page with buttons; clicking the buttons smoothly scrolls the page (actually a container) to anchors located further right. This is done with container.scrollLeft.
Now I'm trying to make it so that when the user scrolls manually (scrollbar, mousewheel, arrow keys etc), the automated smooth scrolling instantly stops.
I've tried doing this with container.addEventListener('scroll',StopScroll,false); but this fires up for any scroll, even done through code, not just done by the user.
Is there a way to detect only user scrolling ? Or maybe a work-around ?
Also, I'd rather not use Jquery, but I'll switch to it if it's the only way.
I've got a feeling that DOM scrolling and event scrolling are managed the same way, and therefore indistinguishable.
However, you might hook into mousedown/keydown and update a variable when a key or mouse button is held, and only perform scrollStop if that variable is set?
I have a div in which there is a link. When a user takes the mouse pointer over the link, I call the basic_nav_mouseover() function which changes the background-image of the parent div. I have also added the function basic_nav_mouseout to the ommouseout attribute of the parent which should set the background-image of the parent div to none when the mouse pointer leaves the div. However, strangely, the function basic_nav_mouseout() is getting called as soon as the mouse pointer in leaving the link in the parent div. Here is a test page : http://spats.in/test/. Look at the links 'about' ,'people','connect' on the top right corner.
Where am I going wrong?
There's a really good explanation of the limitations of the mouseover and mouseout events in the jQuery docs (about half way down that page).
Mouseover and mouseout events trigger when you move the mouse over the bound element, as expected, but they also fire a separate event when you mouse over any inner elements within the parent element - this is obviously undesirable in most circumstances.
Basically, to fix your problem, use the mouseenter and mouseleave events instead.
From a user experience point of view, I'd encourage you to bind both events to the link, so that the special background colour actually indicates that the link is active - I think I'd find the effect you are trying to achieve quite misleading, because the highlighted background would make me think that I can still click the link, even though I cannot..
If you want to keep the visual effect you've current got (with a tall coloured area behind each link), make the link take up the whole box - i.e. 100% of the height and width of the div.
If onmouseover is set on the link, onmouseout should be set on the same element.
onmouseout gets triggered every time a child node is hovered over, you need to check the calling target.
http://www.quirksmode.org/js/events_mouse.html is a good resource.
I'm no javascript expert, but shouldn't you wait with binding the function to the event until the page is fully loaded? So:
window.onload = function(){
$('.item1').bind('mouseleave',basic_nav_mouseout);
};
Also (correct me if I'm wrong) I don't think you have to give the object as an argument in 'basic_nav_mouseout('.item1','red')', you can just use the 'this' keyword. So:
function basic_nav_mouseout(){
this.css('background-image',"none");
}
I don't know anything about the JQuery library though, my only (little) experience is with the Prototype library.