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

In Safari Clipboard.WriteText() does not work in a button on_click callback #561

Open
gdworkman opened this issue Mar 20, 2023 · 3 comments

Comments

@gdworkman
Copy link

Hello,

I am attempting to create a button that copies some text to the user's clipboard. I have included a simplified version of the relevant code below:

put_scope("example_scope")
with use_scope("example_scope):
    put_button('Copy', onclick=example_copy_callback)

def example_copy_callback() -> None:
    text_to_copy = "Hello World"
    run_js("""navigator.clipboard.writeText(out).then(
        () => {
            console.log('Content copied to clipboard');
        }, (err) => {
            console.error('Failed to copy: ', err);
        });""", out = text_to_copy
    )

This is working in both Chrome and Firefox, however with Safari I am getting the following error:
Failed to copy: – NotAllowedError: The request is not allowed by the user agent or the platform in the current context, possibly because the user denied permission.

I believe this has something to do with the fact that in Safari, clipboard.writeText() must be called within user gesture event handlers such as pointerdown or pointerup (source). Unfortunately, I am a noob when it comes to javascript and web development, and I am not clear on how this detail would interact with the underlying onclick callback and run_js() method of PyWebIO.

Any insight into why this is failing or viable workarounds would be greatly appreciated!

@wang0618
Copy link
Member

I failed to set clipboard via clipboard.writeText() in pywebio with chrome.

However, I use a more compatible code to set clipboard in the pywebio's demo in document (like this).

CLIPBOARD_SETUP = """
window.writeText = function(text) {
    const input = document.createElement('textarea');
    input.style.opacity  = 0;
    input.style.position = 'absolute';
    input.style.left = '-100000px';
    document.body.appendChild(input);
    input.value = text;
    input.select();
    input.setSelectionRange(0, text.length);
    document.execCommand('copy');
    document.body.removeChild(input);
    return true;
}
"""
run_js(CLIPBOARD_SETUP)

put_button("Set clioboard", lambda: run_js("writeText(text)", text="Some text"))

You can try the code in here: https://s.pywebio.online/f24f31757b10a0e74b9b874c9588fc78

@gdworkman
Copy link
Author

Thank you for this example.

I considered using a similar approach but was hesitant because document.execCommand is deprecated and no longer recommended. It looks like all major browsers still support it for backwards compatibility, so maybe this is an appropriate workaround for the time being.

@gdworkman
Copy link
Author

Unfortunately the provided example does not work in Safari (tested in Safari version 16.3).

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

No branches or pull requests

2 participants