Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make OnFocus and OnBlur fire synchronously #181

Open
FlowIT-JIT opened this issue Mar 3, 2023 · 2 comments
Open

Make OnFocus and OnBlur fire synchronously #181

FlowIT-JIT opened this issue Mar 3, 2023 · 2 comments

Comments

@FlowIT-JIT
Copy link
Collaborator

FlowIT-JIT commented Mar 3, 2023

The OnFocus and OnBlur events fire asynchronously which might cause problems.

Imagine a control having focus, and we push changes to state when OnBlur fires.
If we have a Save button which immediately persist state, then it won't persist the latest changes from our control, since OnBlur won't be able to push changes in time to be included in the payload.

We might be able to solve this with an implementation similar to this (IE not supported!):

https://jsfiddle.net/we5c6sqv/9/

<input>
<div tabindex="0" id="control">
  <span tabindex="0">
    Hello world
    <span tabindex="0">Hello world - again</span>
  </span><br>
  <input tabindex="0">
</div>
<input>
var c = document.querySelector("#control");

c.addEventListener("focusin", function(e)
{
    //console.log("Focus", e.target, e.relatedTarget, document.activeElement);
	
	var fromOutside = e.relatedTarget === null || (e.relatedTarget !== c && Fit.Dom.Contained(c, e.relatedTarget) === false);
	var receiving = e.target === c || Fit.Dom.Contained(c, e.target) === true;

    if (fromOutside && receiving)
	{
        console.log("%c --- Firing OnFocus", "color: green");
		console.log(" --- Element focused at this point: ", document.activeElement);
    }
});

c.addEventListener("focusout", function(e)
{
    //console.log("Blur", e.target, e.relatedTarget, document.activeElement);
	
	var receiving = e.relatedTarget !== null && (e.relatedTarget === c || Fit.Dom.Contained(c, e.relatedTarget) === true);

    if (receiving === false)
	{
        console.log("%c --- Firing OnBlur", "color: blue");
		console.log(" --- Element focused at this point: ", document.activeElement);
    }
});

/*c.addEventListener("blur", function(e)
{
    console.log("OnBlur - Element focused at this point: ", document.activeElement);
});*/
div, span, input
{
  display: inline-block;
  border: 1px solid red;
  margin: 0.5em;
}

div
{
  border: 2px solid green;
}

*:focus
{
  outline: 2px solid blue;
}
@FlowIT-JIT
Copy link
Collaborator Author

FlowIT-JIT commented Mar 3, 2023

Notice that when onfocusout (or onblur for that matter) fires, focus has not yet been assigned to another element, so document.activeElement will temporarily return <body>, as the example demonstrates. So if we want to be able to obtain the element soon to be focused, we might need to provide it to the event handlers like demonstrated below.
control.OnBlur(function(sender: Fit.Controls.ControlBase, args: { Target: HTMLElement, Origin: HTMLElement | null }) {});
Basically we just need to forward e.target and e.relatedTarget.

@FlowIT-JIT
Copy link
Collaborator Author

FlowIT-JIT commented Mar 10, 2023

Example improved to prove it respects expected event order when control lose focus:
OnMouseDown => Control's OnBlur => OnMouseUp => OnClick
https://jsfiddle.net/6qzenLcg/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant