[IGN-5196]Perspective - Copy to clipboard button

Hi,
is it possible to create this functionality in Perspective (without developing custom component)?

image

Thanks

No, we don’t expose the clipboard API. The modern clipboard API also only works in HTTPS contexts, so it may or may not ever land in Perspective first-party.

I am looking to do something similar with a table. This was 3 years ago. Not sure if any new updates have been provided? Basically, I want a user to be able to click a button to capture all the data from within a table to paste in a email or text file.

I suppose exporting to a text or CSV file might work also. Not as ideal as clipboard.

Hello,

Don't know if this is still in need, but I had the same request, I was able to build in Web Dev

Web Dev


    defaultText = ""

    params = request.get("params", {})

    textToCopy = params.get("text", defaultText)


    if textToCopy == "" and len(params.keys()) > 0:
        firstKey = list(params.keys())[0]
        if firstKey != "text":
            textToCopy = firstKey

    if isinstance(textToCopy, list):
        textToCopy = textToCopy[0] if len(textToCopy) > 0 else defaultText

    textToCopy = str(textToCopy)

    def js_escape(value):
        return value.replace("\\", "\\\\").replace("'", "\\'").replace("\n", "\\n").replace("\r", "")

    jsText = js_escape(textToCopy)

    html = """
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <style>
        html, body {
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
            background: transparent;
            overflow: hidden;
            font-family: Segoe UI, Arial, sans-serif;
        }

        .wrapper {
            width: 100%;
            height: 100%;
            display: flex;
            align-items: center;
            justify-content: flex-start;
            gap: 6px;
        }

        .copy-button {
            width: 24px;
            height: 24px;
            min-width: 24px;
            border: none;
            background: transparent;
            color: #163B77;
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: center;
            padding: 0;
            margin: 0;
            outline: none;
            box-shadow: none;
        }

        .copy-button:hover {
            color: #0078D4;
        }

        .copy-button:active {
            transform: scale(0.92);
        }

        .copy-button.copied {
            color: #107C10;
        }

        .copy-button.error {
            color: #B42318;
        }

        svg {
            width: 20px;
            height: 20px;
            fill: currentColor;
            display: block;
        }

        .copy-message {
            font-size: 12px;
            font-weight: 600;
            color: #107C10;
            white-space: nowrap;
            opacity: 0;
            transform: translateX(-4px);
            transition: opacity 0.16s ease, transform 0.16s ease;
            pointer-events: none;
        }

        .copy-message.show {
            opacity: 1;
            transform: translateX(0);
        }

        .copy-message.error {
            color: #B42318;
        }
    </style>
</head>

<body>
    <div class="wrapper">
        <button class="copy-button" id="copyButton" title="Copiaza grupul" onclick="copyToClipboard()">
            <svg viewBox="0 0 24 24" aria-hidden="true">
                <path d="M16 1H4C2.9 1 2 1.9 2 3v14h2V3h12V1zm3 4H8C6.9 5 6 5.9 6 7v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"></path>
            </svg>
        </button>

        <span class="copy-message" id="copyMessage">Grup copiat!</span>
    </div>

    <script>
        const textToCopy = '__TEXT_TO_COPY__';

        async function copyToClipboard() {
            const button = document.getElementById('copyButton');
            const message = document.getElementById('copyMessage');

            try {
                await navigator.clipboard.writeText(textToCopy);

                button.classList.remove('error');
                button.classList.add('copied');

                message.innerText = 'Grup copiat!';
                message.classList.remove('error');
                message.classList.add('show');

                setTimeout(function() {
                    button.classList.remove('copied');
                    message.classList.remove('show');
                }, 1600);

            } catch (error) {
                button.classList.remove('copied');
                button.classList.add('error');

                message.innerText = 'Nu s-a copiat';
                message.classList.add('error');
                message.classList.add('show');

                setTimeout(function() {
                    button.classList.remove('error');
                    message.classList.remove('show');
                    message.classList.remove('error');
                }, 1800);
            }
        }
    </script>
</body>
</html>
"""

    html = html.replace("__TEXT_TO_COPY__", jsText)

    return {
        "html": html
    }

On my perspective page I have a IFrame component with this src

"/system/webdev/ProjectName/webdevResourceName?text=textToBeCoppied"

When I click on the right icon text from the left label it's copied on the client browser

image

Unfortunately this method works only with text and require web dev module