jsFiddle
Trying to vertically scroll the div child in Google Chrome, arrived at the end, if you try to continue the scroll is also scrolled the div parent, which does not happen with Mozilla. How to fix it?
With jquery you can disable the overflow when mouse is over the child div.
This way works on Firefox 24 for Mint, and Chromium 28...
http://jsfiddle.net/JcUxs/2/
$('.child').on('mouseover',function(){
$(this).parent().addClass('fixoverflow');
});
$('.child').on('mouseleave',function(){
$(this).parent().removeClass('fixoverflow');
});
css:
.fixoverflow{
overflow: hidden
}
I think that this is the best solution I can achieve (It took 1 hour to understand that the scroll event and the wheel is getting trigger both):
I used flag variable to keep the scroller position.
I used jquery and I noticed just now from the comments that you asked for pure javascript.
Anyway jquery bases on native javascript so I'll edit my answer later and translate it to pure code.
Just confirm that it's good enough for you and i'll translate it.
JavscriptCode:
var isCanceled = false;
var currentPos = $(".parent").scrollTop();
var stopWheelTimer = undefined;
$(".child").on('mousewheel', function (event) {
clearTimeout(stopWheelTimer);
event.stopPropagation();
isCanceled = true;
currentPos = $(".parent").scrollTop();
stopWheelTimer = setTimeout(function(){
isCanceled = false;
}, 250);
});
$(".parent").on('mousewheel', function (elem) {
if(isCanceled)
{
$(elem.target).scrollTop(currentPos);
}
});
$(".parent").on('scroll', function (elem) {
if(isCanceled)
{
$(elem.target).scrollTop(currentPos);
}
});
Working Example:
jsFiddle
Related
I have a flash object inside a div, that will zoom it's content when I scroll over it. the problem is that my page also scrolls and I don't know how to fix this problem. I need the page to stand still when I scroll over the flash.
I tried adding this
flashContainer.bind('mousewheel DOMMouseScroll', function(e) {
var scrollTo = null;
if (e.type === 'mousewheel') {
scrollTo = (e.originalEvent.wheelDelta * -1);
} else if (e.type === 'DOMMouseScroll') {
scrollTo = 40 * e.originalEvent.detail;
}
if (scrollTo) {
e.preventDefault();
$(this).scrollTop(scrollTo + $(this).scrollTop());
}
});
but because of preventDefault, the flash object won't zoom anymore.
Do you have any suggestions?
may be this could work for you:
$("element").hover(function(){
var scrollT = $(document).scrollTop();
$(document).on("scroll", function(e){
$(document).scrollTop(scrollT);
});
}, function(){
$(document).off("scroll");
});
http://jsfiddle.net/ZFsDY/3/
I stumbled on this issue a few months ago (the old method we used to manage scrolling didn't work on the most recent browsers).
I'm not allowed to publish the code for it, but here a few note on how we did it.
Like in reyaner's answer, we use event listening and preventDefault() to disable the browser auto scrolling, and get the scroll value (but without scrollTop()).
Once we have the value, we send it to the Flash via ExternalInterface.
For it to be possible, the flash object must beforehand add a Callback, a Flash method that can be called by Javascript.
We added a couple of additional interaction between Flash and JS so that the scroll is locked only when the Flash has the focus.
A warning : all browser don't have the same scale for the wheelDelta, and you may find that the zoom speed can vary. To fix this we decided to always use a fixed step each time the event is dispatched, instead that using the delta as-is.
another try:
$("element").bind( 'mousewheel DOMMouseScroll', function ( e ) {
var d = e.wheelDelta || -e.detail;
var s;
if(d < 0) s = 1;
else s = -1;
this.scrollTop += s * 30;
e.preventDefault();
});
http://jsfiddle.net/ZFsDY/5/
I have a flyover dropdown menu and when I scroll down the page this menu need to appear all the time. I have this below code which is working fine for FFox and chrome but IE8 and I hope IE9 its not working. Not sure whats causing the issue. Please suggest if any change need to be done to work with IE as well
var name = ".cssMenu";
//var menuYloc = null;
$(document).ready(function(){
//menuYloc = parseInt($(name).css("top").substring(0,$(name).css("top").indexOf("px")))
$(window).scroll(function () {
if($(this).scrollTop()>70){
offset =$(document).scrollTop()-70+"px";
}
else
{
offset = $(document).scrollTop()+"px";
}
$(name).css("top",offset);
});
});
i blind shoot suspect it being the order its executed. try wrapping it in () like:
`offset =($(document).scrollTop()-70)+"px";`
I just found out that my script is working fine in Chrome, but not in FireFox - and I can't figure out why.
This is the site in development: www.fireflycovers.com
The script should execute when one of the round green buttons is clicked. (scrolls the window to the next container)
The script looks like this at the moment:
$('.scroll').css('display' , 'block');
$('.scroll').on('click', function(e) {
var container = $(this).parent();
// Scans if last container in group
while (document != container[0] &&
container.find('~.col, ~:has(.col)').length == 0) {
// If so, search siblings of parent instead
var container = container.parent(),
nextdiv = container.nextAll('.col, :has(.col)').first();
}
// Back to first .col (when no next .col)
if (nextdiv.length == 0) {
nextdiv = $(document).find('.col:first')
};
// Animates scrolling to new position
$('body').animate({scrollTop:nextdiv.offset().top}, 1000);
return false;
});
});
Did you try debugging at all? As in, putting console.log statements throughout your method to see what the values of things are at certain times and watching it execute? Anyway, does using this help at all?
$('body,html').animate({scrollTop:nextdiv.offset().top}, 1000);
Verified from Animate scrollTop not working in firefox
You need html because firefox behaves differently when it comes to overflow.
I have been experimenting with jscrollpane to add custom scrollbars to some content. The data is being pulled in via ajax and the jscrollpane api works nicely for that.
But I'm trying to make the scrollpane have a height that is always, say, 70% of the height of the users browser window. The jscrollpane site says that I can use the following code to make it work, but i'm having no luck.
$(function () {
$('.scroll-pane').each(
function () {
$(this).jScrollPane({
showArrows: $(this).is('.arrow')
});
var api = $(this).data('jsp');
var throttleTimeout;
$(window).bind('resize', function () {
if ($.browser.msie) {
// IE fires multiple resize events while you are dragging the browser window which
// causes it to crash if you try to update the scrollpane on every one. So we need
// to throttle it to fire a maximum of once every 50 milliseconds...
if (!throttleTimeout) {
throttleTimeout = setTimeout(
function () {
api.reinitialise();
throttleTimeout = null;
}, 50);
}
} else {
api.reinitialise();
}
});
})
});
When I change the css to a percentage, the custom scrollbar fails entirely, and I get a default chrome scrollbar that is 100% of the height of the window.
http://jsfiddle.net/loren_hibbard/2yEsG/
Thank you very much!
It appears that there is some compatibility problem with the api for resize and jsfiddle. jscrollpane continues to be an amazing extension. thanks.
The best way to understand this is to look at this fiddle.
Notice how mouse wheel over the fixed content in the red box does nothing. I would like the scrollable div to scroll.
In case the fiddle dies - basically I have a scrollable div with a fixed element over it. Typically when you mouse wheel over a scrollable div it will of course scroll. But if you are over the fixed element instead then no scroll happens. Depending on your site layout this could be counter intuitive to a user.
jQuery solutions are okay.
A much, MUCH simpler, but much less widely supported, answer is the following:
#fixed{ pointer-events:none; }
jsFiddle
Doesn't work in IE at all though unfortunately! But you could use modernizr or somesuch to detect whether it was supported and use the jQuery as a stop-gap where it isn't.
Courtesy of Mr. Dominic Stubbs
I had this problem and this works for me (using jquery):
$(document).ready( function (){
$('#fixed').on('mousewheel',function(event) {
var scroll = $('#container').scrollTop();
$('#container').scrollTop(scroll - event.originalEvent.wheelDeltaY);
return true;
});
});
Works on Safari and Chrome: http://jsfiddle.net/5bwWe/36/
I think this does what you're asking for!
$('#fixed').bind('mousewheel', function(e){
var scrollTo= (e.wheelDelta*-1) + $('#container').scrollTop();
$("#container").scrollTop(scrollTo);
});
EDIT: Updated the jsFiddle link to one that actually works
DOUBLE EDIT: Best to dispense with the .animate() on further testing...
jsFiddle Example
TRIPLE EDIT:
Much less pretty (and will probably be horribly slow with a lot of elements on the page), but this works and I owe a lot to this stackoverflow answer.
$('#fixed').bind('mousewheel', function(e) {
var potentialScrollElements = findIntersectors($('#fixed'), $('*:not(#fixed,body,html)'));
$.each(potentialScrollElements, function(index, Element) {
var hasVerticalScrollbar = $(Element)[0].scrollHeight > $(Element)[0].clientHeight;
if (hasVerticalScrollbar) {
var scrollTo = (e.wheelDelta * -1) + $(Element).scrollTop();
$(Element).scrollTop(scrollTo);
}
});
});
function findIntersectors(targetSelector, intersectorsSelector) {
var intersectors = [];
var $target = $(targetSelector);
var tAxis = $target.offset();
var t_x = [tAxis.left, tAxis.left + $target.outerWidth()];
var t_y = [tAxis.top, tAxis.top + $target.outerHeight()];
$(intersectorsSelector).each(function() {
var $this = $(this);
var thisPos = $this.offset();
var i_x = [thisPos.left, thisPos.left + $this.outerWidth()]
var i_y = [thisPos.top, thisPos.top + $this.outerHeight()];
if (t_x[0] < i_x[1] && t_x[1] > i_x[0] && t_y[0] < i_y[1] && t_y[1] > i_y[0]) {
intersectors.push($this);
}
});
return intersectors;
}
UPDATE (August 2016): It seems the browser implementations have changed and it's no longer possible to re-dispatch a WheelEvent on a different target. See the discussion here.
For an alternative solution that should work across platforms, try this:
var target = $('#container').get(0);
$('#fixed').on('wheel', function (e) {
var o = e.originalEvent;
target.scrollTop += o.deltaY;
target.scrollLeft += o.deltaX;
});
Working example: https://gist.run/?id=6a8830cb3b0564e7b16a4f31a9405386
Original answer below:
Actually, the best way to do it is to copy the original event. I've tried #Tuokakouan's code but scrolling behaves strangely (too fast) when we use a multitouch touchpad that has inertia.
Here's my code:
var target = $('#container').get(0);
$('#fixed').on('wheel', function(e){
var newEvent = new WheelEvent(e.originalEvent.type, e.originalEvent);
target.dispatchEvent(newEvent);
});
You can try it here: http://jsfiddle.net/NIXin/t2expL6u/1/
What I'm trying to do now is also to pass the touch events, without much success. Since mobile phones and touch screens are now more popular, some people might want to scroll using their fingers instead - neither of the answers offered solves that.
Well,all solutions with js are kind of delayed when scrolling on it. if the fixed element you use is just for display, then I have a good css tricks to achieve that.
make the fixed element z-index:-1 and the container element background-color:transparent
here is the jsfiddle you can see: https://jsfiddle.net/LeeConan/4xz0vcgf/1/