Scrollbar problem with jQuery UI dialog in Chrome

2019-01-16 18:19发布

问题:

I'm using the jQuery UI dialog with modal=true. In Chrome and Safari, this disables scrolling via the scroll bar and cursor keys (scrolling with the mouse wheel and page up/down still works).

This is a problem if the dialog is too tall to fit on one page - users on a laptop get frustrated.

Someone raised this three months ago on the jQuery bug tracker - http://dev.jqueryui.com/ticket/4671 - it doesn't look like fixing it is a priority. :)

So does anyone:

  1. have a fix for this?
  2. have a suggested workaround that would give a decent usability experience?

I'm experimenting with mouseover / scrollto on bits of the form, but it's not a great solution :(

EDIT : props to Rowan Beentje (who's not on SO afaict) for finding a solution to this. jQuery UI prevents scrolling by capturing the mouseup / mousedown events. So the code below seems to fix it:

$("dialogId").dialog({
    open: function(event, ui) {
        window.setTimeout(function() {
            jQuery(document).unbind('mousedown.dialog-overlay')
                            .unbind('mouseup.dialog-overlay');
        }, 100);
    },
    modal: true
});

Use at own risk, I don't know what other unmodal behaviour unbinding this stuff might allow.

回答1:

I agree with the previous posters in that if the dialog is not working for you, it may be good to rethink your design. However, I can offer a suggestion.

Could you put the dialog content inside a scrollable div? That way instead of the whole page needing to scroll, just the content inside the div would need to scroll. This workaround should be pretty easy to accomplish too.



回答2:

You can use this code : jquery.ui.dialog.patch.js

It solved the problem for me. Hope this is the solution that you're looking for.



回答3:

While I agree with, the folks in the party of not making a dialog that is bigger than the viewport, I think there are cases where scrolling may be necessary. A dialog might look very good in a resolution greater the 1024 x 768, but anything less looks crunched. Or say for instance you never want a dialog to show up over the header of your site. In my case I have ads that occassionally have flash z-index problems, so I never want dialogs to show above them. Finally, it is bad in general to take away any sort of common control, like scrolling, away from the user. This is a problem separate from how big the dialog is.

I would be interested in knowing why the those mousedown and mouseup events are there in the first place.

I tried the solution that alexis.kennedy provided and it works break without breaking anything that I can see in any browser.



回答4:

I workaround this situation by disabling dialog modal mode and showing overlay manually:

function showPopup()
{
    //...

    // actionContainer - is a DIV for dialog

    if ($.browser.safari == true)
    {
        // disable modal mode
        $("#actionContainer").dialog('option', 'modal', false);

        // show overlay div manually
        var tempDiv = $("<div id='tempOverlayDiv'></div>");
        tempDiv.css("background-color", "#000");
        tempDiv.css("opacity", "0.2");
        tempDiv.css("position", "absolute");
        tempDiv.css("left", 0);
        tempDiv.css("top", 0);
        tempDiv.css("width", $(document).width());
        tempDiv.css("height", $(document).height());
        $("body").append(tempDiv);
    }

    // remove overlay div on dialog close
    $("#actionContainer").bind('dialogclose', function(event, ui) {
        $("#tempOverlayDiv").remove();      
    });

    //...
}


回答5:

I believe having too big dialogs is against your 'decent usability experience' requirement. Even if you didn't have to have a workaround due to the jQuery UI Dialog bug, I'd get rid of such big dialogs. Anyway, I do understand there may be some 'extreme' cases in which you need to adapt, so...

That said, it would certainly help if you attached some screenshot - you're asking a question about a design, but we can't see it. But I understand you might not be able/willing to show the contents of it so that's fine. These are my blind guesses; hope you find them useful:

  • Try a different layout for your dialog. If you do this, do it for all dialogs, not just the ones you're having problem with (users don't like to learn many different UIs).
  • If you can't find a different layout, try widening your dialog first. IF you have many options to choose from, you might find a good solution by dividing them in two columns.
  • Knowing you're already using jQuery UI, try using tabs. If you have too many options, a tabbed panel is usually a good solution - users are 'used' to that widget.
  • You talked about 'items' in the dialog, but we don't know what an item is. Is it possible at all to show them in a 'summarized' way such as a small list at the left and an expanded view at the right when you click on them? For example, having a list with the items titles at the left, and when you click them you get the full display on the right.

Without being able to see the design, I guess that's as far as I can go.



回答6:

There is a workaround that unbind the binded event. This adds the following in the open: event of the dialog :

$("#longdialog").dialog({
    modal:true,
    open: function (event, ui) { window.setTimeout(function () {
        jQuery(document).unbind('mousedown.dialog-overlay').unbind('mouseup.dialog-overlay'); }, 100);
    }
});

This works ... but this is ugly

--from https://github.com/jquery/jquery-ui/pull/230#issuecomment-3630449

Worked like a charm in my case.



回答7:

This is a bug that has been since fixed: http://bugs.jqueryui.com/ticket/4671



回答8:

Did you try my extension to the Dialog? http://plugins.jquery.com/project/jquery-framedialog



回答9:

Use the code below. It will work fine.

$("dialogId").dialog({
      open: function(event, ui) {
            window.setTimeout(function() {
            jQuery(document).unbind('mousedown.dialog-overlay')
                        .unbind('mouseup.dialog-overlay');
             }, 100);
      },
      modal: true,
      safariBrowser: (function( $, undefined ) {
               if ($.ui && $.ui.dialog) {
                   $.ui.dialog.overlay.events = $.map('focus,keydown,keypress'.split(','), function(event) { return event + '.dialog-overlay'; }).join(' ');
               }
 }(jQuery))
});