Halil Ibrahim
Halil Ibrahim

Reputation: 1369

Google chrome scroll overflow bug

Its a wierd bug and it was hard to figure out.

We create a map application and there is a select element on a pop-up. It has size attribute setted. The parent of select element has overflow:auto style. When scroll is appered, trying to select something on select element scrolls body down. But body has overflow:hidden style and it kills us.

Here is two fiddles i created:

http://jsfiddle.net/e6BK3/1/

http://jsfiddle.net/e6BK3/8/

Try to select first option on select element when its not focused on google chrome. Then see it scrolls all parent elements avalibale to scroll.

Google Chrome Version : 34.0.1847.131

Upvotes: 4

Views: 3418

Answers (2)

paulalexandru
paulalexandru

Reputation: 9530

If you want to achieve this in google chrome all you have to do is to:

  • Load jQuery in you project (probably you already did)
  • Put this code into your CSS

CSS:

select:focus {
    outline: 0;
}

Put this code into your javascript:

$('.innder-div').on('scroll', function() {
    $(this).scrollTop(0);     
})

$('.root').on('scroll', function() {
    $(this).scrollTop(0);     
})

$('select').on('mouseover', function(){
    $(this).focus();
})

Jsfiddle here

Update: Another solution is to use middle click (wheel button) before the left click on the select box and all will work as normal. So the solution is to use javascript to detect the first click and trigger the middle button click before it and only after that the mouse left button.

Upvotes: 2

M'sieur Toph'
M'sieur Toph'

Reputation: 2676

I think I did it! :)

The point is to prevent any other propagation on the option tag mousedown event, and manage manually the focusing of the select box.

See the jsFiddle

I tried to make it as clear as I can :

$('option')
.on('mousedown', function(e){
    // Prevent any other propagations
    e.stopImmediatePropagation();

    // Focus on the select DOM element
    // but saving the scrollTop of each parent before
    $(this)
    .parents()
    .filter(function(){
        // filter only those which have a scroll visible
        return $(this)[0].scrollHeight > $(this)[0].clientHeight;
    })
    .each(function(_,elt){
        // and for each, save the scroll value in data set
        $(elt).data('saveScroll', $(elt).scrollTop());
    })

    // Then trigger the focus option of the select DOM element
    // And finally the custom 'scrollback' event
    $(this).parent('select')
    .trigger('focus')
    .trigger('scrollback');

});

$('select')
// This customized event is for getting back the value of the scroll of all parents
// only if this value exists
.on('scrollback'
    , function(e){
        $(this)
        .parents()
        .filter(function(){
            // filter only those which have this data in data-set
            return 0 === $(this).data('saveScroll') || ~~$(this).data('saveScroll');
        })
        .each(function(_,elt){
            // and for each, putting back the right scroll value
            $(elt).scrollTop($(elt).data('saveScroll'));
            $(elt).removeData('saveScroll');
        })
    });

This is probably not perfect because it is a hack.

At least it even worked with multiple-typed select. And it is cross-browser compliant.

Upvotes: 2

Related Questions