I like the general idea, but I think it can be simplified and maybe made more 
stable if you just go ahead and create the proxy button whether activeElement 
can be used or not. There shouldn't be a performance issue as it's always user 
initiated and can be removed from dom after use.

What do you think?
________________________________
From: Maria Jose Esteve <mjest...@iest.com>
Sent: Thursday, April 24, 2025 2:12 AM
To: Yishay Weiss <yishayj...@hotmail.com>; dev@royale.apache.org 
<dev@royale.apache.org>
Cc: Harbs <harbs.li...@gmail.com>
Subject: RE: mx.net.FileReference chrome


I have done a little investigation [1], and I propose the following changes to 
the bead [2]:



- Added “isElementClickFriendly(el:WrappedHTMLElement)” to verify if the 
current “document.activeElement” is a valid trigger for programmatic “.click()” 
based on visibility, interactivity, and semantics.

  (Maybe this feature could be moved to some kind of utilities)

- If the active element is not valid, a fallback invisible proxy button is 
created and used to trigger the “input[type=file]” click safely.

- Avoids use of “display: none” on the proxy element, using “position: 
absolute”, “opacity: 0” and “left: -9999px” instead - ensuring Chrome accepts 
the interaction.

- Keeps existing logic for cancel detection, “modelChanged” dispatch, and 
encapsulation intact.



How do you see it now?



Hiedra



[1]

In HTML/DOM, most elements can handle click events, but some don't accept them 
by default or don't make sense as clickable elements, especially if they're 
disabled, don't render visually, or don't participate in the browser's 
interactive tree.

As elements that don't accept "click" directly (or don't make sense for them to 
do so):

<meta>                 Doesn't render anything, just metadata

<title>                    Not visible/interactive in the DOM

<script>                 Only contains code, no UI

<style>                  Only defines CSS, not part of the UI

<link> (no href)   If it doesn't point to something, it's not interactive

<base>                  Defines base URL, not visible or clickable

<param>               Used inside <object>, not visual

<source>              In <audio>, <video>, not visible

<track>                  Like <source>, not directly displayed

<template>          Its content is not automatically rendered

<noscript>            Only displayed if JS is disabled



Also to consider:

- Disabled elements (<button disabled>, <input disabled>, etc.) do not trigger 
clicks.

- Hidden elements (display: none or visibility: hidden) do not trigger clicks 
either.

- Plain text in the DOM (text nodes) cannot receive events directly.

- SVGs or canvases without specific listeners may not capture clicks depending 
on how they are structured.



Although it's also worth keeping in mind that you can force something to 
receive a click. Any element can receive a click event if we apply:

element.tabIndex = 0; // o -1

element.addEventListener("click", function() { ... });



[2] 
https://github.com/apache/royale-asjs/commit/64782b4a003a9ac22a056833abd6e378813517a7

https://github.com/apache/royale-asjs/blob/64782b4a003a9ac22a056833abd6e378813517a7/frameworks/projects/Network/src/main/royale/org/apache/royale/file/beads/FileBrowser.as



De: Yishay Weiss <yishayj...@hotmail.com>
Enviado el: miércoles, 23 de abril de 2025 15:20
Para: Maria Jose Esteve <mjest...@iest.com>; dev@royale.apache.org
CC: Harbs <harbs.li...@gmail.com>
Asunto: Re: mx.net.FileReference chrome



I don't think activeElement can necessarily dispatch a click() event...

________________________________

From: Maria Jose Esteve <mjest...@iest.com>
Sent: Wednesday, April 23, 2025 12:58 PM
To: dev@royale.apache.org <dev@royale.apache.org>
Cc: Harbs <harbs.li...@gmail.com>; Yishay Weiss <yishayj...@hotmail.com>
Subject: RE: mx.net.FileReference chrome



The email subject is incorrect, please forgive me. The fix I'm proposing is for 
the core bead org.apache.royale.file.beads.FileBrowser.
Last week, I made some changes to address unintended behavior in browsers like 
Chrome. I've been actively working with my application since I made the change 
locally, and everything works fine. I've also tested the code that Cristallium 
uses in theirs, and it also works fine.
One of the two issues is solved by increasing the value of the CANCEL_TIMEOUT 
constant. For now, I've modified it directly, but it might be better to 
implement a more flexible modification, such as creating a property. For now, 
I'm going to leave it as is, and if in the future someone more skilled than me 
thinks we should do it differently, we'll change it.

@Harbs, @Yishay Weiss I know spectrum-royale uses this bead, for example in the 
DropZone component. Could you test the modification I proposed to make sure it 
won't affect this project?

I'm going to wait until Friday to port this small FileBrowser modification to 
royale-asjs.
Hiedra

-----Mensaje original-----
De: Maria Jose Esteve <mjest...@iest.com>
Enviado el: martes, 15 de abril de 2025 1:24
Para: dev@royale.apache.org
Asunto: RE: mx.net.FileReference chrome

I've already solved it by "modifying FileBrower.as" do you think it's correct 
to commit it?

public function browse():void
                {
                        COMPILE::SWF
                        {
                                delegate.browse();
                        }
                        COMPILE::JS
                        {
                                focusedButton = document.activeElement as 
WrappedHTMLElement;
                                //trace("activeElement is: " + focusedButton);
                                focusedButton.addEventListener("blur", 
blurHandler);
                                focusedButton.addEventListener("focus", 
focusHandler);
                                window.addEventListener("keydown", keyHandler);
                                window.addEventListener("mousemove", 
mouseHandler);
                                window.addEventListener("mousedown", 
mouseHandler);
                                //delegate.click();
                                focusedButton.addEventListener("click", 
clickHandler);
                                focusedButton.click();
                                focusedButton.removeEventListener("click", 
clickHandler);
                        }
                }

                //New
                COMPILE::JS
                private function clickHandler(e:Object):void
                {
                        delegate.click();
                }

This way there are no problems, everything is legal for Chrome, BUT the same 
problem occurs again as https://github.com/apache/royale-asjs/issues/886
If I increase the CANCEL_TIMEOUT constant to 250, everything works fine.
What would be the best way to change the value of the static constant 
CANCEL_TIMEOUT?

Hiedra

-----Mensaje original-----
De: Josh Tynjala <joshtynj...@bowlerhat.dev> Enviado el: lunes, 14 de abril de 
2025 21:21
Para: dev@royale.apache.org
Asunto: Re: mx.net.FileReference chrome

I just tested one of my non-Royale apps that calls click() on the <input 
type="file"> element. It still works in that app when tested in Chrome.
It's a very similar situation, where I have a separate <div> element with a 
"click" listener, and the listener calls click() on the <input type="file"> 
element.

Perhaps you should add a breakpoint in the debugger and check what your call 
stack looks like. Maybe there's a clue there.

--
Josh Tynjala
Bowler Hat LLC
https://bowlerhat.dev/


On Mon, Apr 14, 2025 at 11:37 AM Maria Jose Esteve <mjest...@iest.com>
wrote:

> Yes, I understand the problem; it's not new, and I understand that
> Chrome must have tightened this policy.
>
> I'm wondering if, just as we added the Input-Type-file (delegate), it
> would be appropriate to add a "hidden button" that would call
> delegate.browser.
>
> I've run a test. I created a button in the createDelegate() function,
> called delegateFileButton, and in its "click" event I called
> delegate.click [1] and in the browse function I launched a
> delegateFileButton.click() [2] but it didn't work. ☹ (In FireFox it
> still works fine)
>
>
>
> [1]
>
> COMPILE::JS
>
>                                public function createDelegate():void
>
>                                {
>
>                                                delegate =
> document.createElement('input') as WrappedHTMLElement;
>
>
>  delegate.setAttribute('type', 'file');
>
>
>  goog.events.listen(delegate, 'change', fileChangeHandler);
>
>
>
>                                                delegateFileButton =
> document.createElement('button') as WrappedHTMLElement;
>
>
>  delegateFileButton.style.display = "none";
>
>
> delegateFileButton.onclick = function():void {
>
>
>      delegate.click();
>
>                                                                };
>
>                                                // I have also tried this:
>
>                                                /*
>
>
>  goog.events.listen(delegateFileButton, 'click',
>
>                                                function():void {
>
>
>      delegate.click();
>
>                                                                } );
>
>                                                */
>
>                                                }
>
> [2] public function browse():void
>
>                                {
>
>                                                COMPILE::SWF
>
>                                                {
>
>
>  delegate.browse();
>
>                                                }
>
>                                                COMPILE::JS
>
>                                                {
>
>
>  focusedButton = document.activeElement as WrappedHTMLElement;
>
>
>  //trace("activeElement is: " + focusedButton);
>
>
>  focusedButton.addEventListener("blur", blurHandler);
>
>
>  focusedButton.addEventListener("focus", focusHandler);
>
>
>  window.addEventListener("keydown", keyHandler);
>
>
>  window.addEventListener("mousemove", mouseHandler);
>
>
>  window.addEventListener("mousedown", mouseHandler);
>
>
>  delegateFileButton.click();
>
>                                                }
>
>                                }
>
>
>
>
>
> Hiedra
>
>
>
> -----Mensaje original-----
> De: Josh Tynjala <joshtynj...@bowlerhat.dev<mailto:
> joshtynj...@bowlerhat.dev>>
> Enviado el: lunes, 14 de abril de 2025 19:36
> Para: dev@royale.apache.org<mailto:dev@royale.apache.org>
> Asunto: Re: mx.net.FileReference chrome
>
>
>
> Browsers have certain security restrictions where you can't call
> certain APIs unless the user has interacted with the page in some way.
> In this case, if you want to call FileReference.browse(), it must be
> triggered by a listener for a user gesture, such as mouse click or key down.
>
>
>
> --
>
> Josh Tynjala
>
> Bowler Hat LLC
>
> https://bowlerhat.dev/
>
>
>
>
>
> On Mon, Apr 14, 2025 at 9:42 AM Maria Jose Esteve <mjest...@iest.com
> <mailto:mjest...@iest.com>> wrote:
>
>
>
> > Hi,
>
> > I need your help because I'm stuck.
>
> > In one of my applications, I use mx.net.FileReference to select a
>
> > user's photo.
>
> > It's always worked fine for me, but yesterday, while testing, I
>
> > noticed that it stopped working in Chrome, although it still works
> > as
>
> > expected in Firefox.
>
> > I'm not getting any errors, but I do see a warning in the debug console:
>
> > "File chooser dialog can only be shown with a user activation."
>
> > The traceback points to org.apache.royale.file.beads.FileBrowser in
>
> > the
>
> > browse() method:
>
> >
>
> > public function browse():void
>
> >         {
>
> >             COMPILE::SWF
>
> >             {
>
> >                 delegate.browse();
>
> >             }
>
> >             COMPILE::JS
>
> >             {
>
> >                 focusedButton = document.activeElement as
>
> > WrappedHTMLElement;
>
> >                 //trace("activeElement is: " + focusedButton);
>
> >                 focusedButton.addEventListener("blur", blurHandler);
>
> >                 focusedButton.addEventListener("focus",
> > focusHandler);
>
> >                 window.addEventListener("keydown", keyHandler);
>
> >                 window.addEventListener("mousemove", mouseHandler);
>
> >                 window.addEventListener("mousedown", mouseHandler);
>
> >                 delegate.click(); // <<<<<<<<<<
>
> > -------------------------- Error
>
> >             }
>
> >         }
>
> >
>
> > I've verified that the delegate is still valid; it references the
>
> > "input, type file" that's created.
>
> > Any ideas on how to fix this?
>
> >
>
> > Thx.
>
> > Hiedra
>
> >
>
> >
>

Reply via email to