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

DatePicker: Focused() returns false when interacting with calendar widget #194

Closed FlowIT-JIT closed 10 months ago

FlowIT-JIT commented 11 months ago

See the following example:

https://jsfiddle.net/oaem3fkd/3/

Fit.Events.OnReady(function()
{
    var appContainer = document.querySelector("#MyApp");

    var dp = new Fit.Controls.DatePicker("DatePicker1");    
    dp.Width(100);
    dp.OnFocus(function(sender) { console.log("OnFocus"); });
    dp.OnBlur(function(sender) { console.log("OnBlur"); });
    dp.Render(appContainer);
    dp.Show();

    appContainer.addEventListener("blur", function(e)
    {
        console.log("DatePicker focused: ", dp.Focused());
        console.log("Focused element: ", document.activeElement);

        // Imagine a scenario where the control is
        // removed when focus is lost. It now will
        // when interacting with the calendar widget.
        /*if (dp.Focused() === false)
        {
            dp.Dispose();
        }*/

    }, true); // True = capture phase
});

In this case Focused() returns false (see the browser console), even though the control is considered having focus.

FlowIT-JIT commented 10 months ago

Reopening due to related issue: https://jsfiddle.net/6yep1jhu/2/

Interacting with the arrow buttons in the calendar widget, changing month or year with the select controls, or clicking in a blank area in the calendar widget, causes the focusout event to be triggered with relatedTarget being null. We have a React app which rerenders and unmounts the control due to this scenario making the DatePicker almost useless. Only selecting (clicking) a day in the calendar widget works.

We can ensure that relatedTarget does not become null by catching focus as it "leaves" the control using tabIndex. This does not work when changing month or year though.

Fit._internal.ControlBase.ReduceDocumentRootPollution = true;

Fit.Events.OnReady(function()
{
    var appContainer = document.querySelector("#MyApp");
    //appContainer.tabIndex = -1; // Retaining focus using tabindex prevents destruction when interacting with calendar

    var dp = new Fit.Controls.DatePicker("DatePicker1");    
    dp.Width(100);
    dp.OnFocus(function(sender) { console.log("OnFocus"); });
    dp.OnBlur(function(sender) { console.log("OnBlur"); });
    dp.Render(appContainer);
    dp.Show();

    document.body.addEventListener("focusout", function(e)
    {
        console.log("FocusOut", e.relatedTarget);

        if (e.relatedTarget === null)
        {
            dp.Dispose();
        }

    });
});