Jemt / Fit.UI

Fit.UI is a JavaScript based UI framework built on Object Oriented principles
http://fitui.org
GNU Lesser General Public License v3.0
19 stars 7 forks source link

DropDown: Pull down menu opens to the wrong side #189

Open Jemt opened 1 year ago

Jemt commented 1 year ago

See https://jsfiddle.net/kvu2qcrm/6/

Try the 3 test cases in the JavaScript code. Notice how the combination of DropDownMaxWidth(600) + DetectBoundaries(true) causes the pull down menu to open to the left side, rather than to the right as expected.

image

Code from JSFiddle

HTML

<div id="Control"></div>

CSS

body
{
    font-family: verdana;
    font-size: 14px;
    color: #333;
}

div#Control
{
    text-align: center;
}

JavaScript

Fit.Events.OnReady(function()
{
    var lv = new Fit.Controls.ListView();
    Fit.Array.ForEach(GetUsers(), function(user)
    {
        lv.AddItem(user.Name, user.Mail);
    });

    var dd = new Fit.Controls.DropDown("DropDown1");
    dd.SetPicker(lv);
    dd.MultiSelectionMode(true);
    dd.Width(200);
    dd.DropDownMaxHeight(150);
    dd.InputEnabled(true);
    dd.Render(document.querySelector("#Control"));

    // Try the 3 test cases below.
    // IMPORTANT: Resize viewport of test page to a width of 1100px before testing !!!

    // Test case 1
    // DropDownMaxWidth(9999) causes pull down menu to open to the right side as expected.
    // The pull down menu might exceed the boundaries of the viewport though which is fine.
    //dd.DropDownMaxWidth(9999);

    // Test case 2 (BUG)
    // DropDownMaxWidth(600) combined with DetectBoundaries(true)
    // results in pull down menu opening to the left side, even
    // though there is plenty of space to the right side to accommodate
    // the MaxWidth of 600px.
    dd.DropDownMaxWidth(600);
    dd.DetectBoundaries(true);

    // Test case 3
    // If we instead of DetectBoundaries(true) uses DetectBoundaries(true, true),
    // then the pulldown menu opens to the right side as one would expect.
    //dd.DropDownMaxWidth(600);
    //dd.DetectBoundaries(true, true);

    if (Fit.Browser.IsMobile())
        dd.Width(100, "%");
});

// ============================
// Get demo data
// ============================

window.GetUsers = function(picker)
{
    var users =
    [
        { Name: "James Thomson James Thomson James Thomson James Thomson James Thomson James Thomson", Mail: "james@server.com" },
        { Name: "Hans Törp", Mail: "hans@server.com" },
        { Name: "Ole Shortsom", Mail: "ole@server.com" },
        { Name: "Michael Burström", Mail: "michael@server.com" },
        { Name: "Ilda Longstum", Mail: "ilda@server.com" },
        { Name: "Martin Grom", Mail: "martin@server.com" },
        { Name: "Anders Handsom", Mail: "anders@server.com" },
        { Name: "Jacob Marking", Mail: "jacob@server.com" },
        { Name: "Jan Jacksson", Mail: "jan@server.com" },
        { Name: "Christian Fros", Mail: "christian@server.com" }
    ];

    return users;
}
Jemt commented 1 year ago

Here the left/right position is determine for DetectBoundaries(true): https://github.com/Jemt/Fit.UI/blob/ade73e731e9e4dbfba5abbbfd7296588c3ca82ba/Controls/DropDown/DropDown.js#L2494

Here the right/right position is determined for DetectBoundaries(true, true) - relative to viewport: https://github.com/Jemt/Fit.UI/blob/ade73e731e9e4dbfba5abbbfd7296588c3ca82ba/Controls/DropDown/DropDown.js#L2627

Jemt commented 1 year ago

This also seems less than optimal. If e.g. DropDownMaxWidth(100, "em") is configured, the calculated pixel width will be returned and become the basis of the calculation of space available - but the pull down menu might not even assume a width of 100em - remember, this is max-width, not actual width. It would be better if we could obtain offsetWidth from the pulldown menu instead.

https://github.com/Jemt/Fit.UI/blob/ade73e731e9e4dbfba5abbbfd7296588c3ca82ba/Controls/DropDown/DropDown.js#L2410

Jemt commented 1 year ago

Bonus bug found. If we use DetectBoundaries(true, true) without configuring DropDownMaxWidth(..), then the pull down menu exceeds the boundaries of the viewport: https://jsfiddle.net/7vhewxgq/

image