diff --git a/Framework/Frontend/js/src/components/CopyToClipboardComponent.js b/Framework/Frontend/js/src/components/CopyToClipboardComponent.js index ccc4c898a..ccc5d0ded 100644 --- a/Framework/Frontend/js/src/components/CopyToClipboardComponent.js +++ b/Framework/Frontend/js/src/components/CopyToClipboardComponent.js @@ -32,15 +32,26 @@ export class CopyToClipboardComponent extends StatefulComponent { * Copies the specified text to the clipboard. * * @param {string} clipboardTargetValue The text to be copied to the clipboard. + * @param {function} onFailure The callback function to be invoked if copying to the clipboard fails. * @returns {void} */ - copyToClipboard(clipboardTargetValue) { - navigator.clipboard.writeText(clipboardTargetValue); - this._successStateTimeout = setTimeout(() => { - this._successStateTimeout = null; + async copyToClipboard(clipboardTargetValue, onFailure) { + try { + await navigator.clipboard.writeText(clipboardTargetValue); + if (this._successStateTimeout) { + clearTimeout(this._successStateTimeout); + } + + this._successStateTimeout = setTimeout(() => { + this._successStateTimeout = null; + this.notify(); + }, 2000); this.notify(); - }, 2000); - this.notify(); + } catch (error) { + if (onFailure) { + onFailure(error); + } + } } /** @@ -85,11 +96,18 @@ export class CopyToClipboardComponent extends StatefulComponent { * Renders the button that allows copying text to the clipboard. * * @param {vnode} vnode The virtual DOM node containing the attrs and children. + * @param {object} vnode.attrs The attributes passed to the component. + * @param {string} vnode.attrs.value The text to be copied to the clipboard. + * @param {string} vnode.attrs.id The unique identifier for the copy button will become 'copy-{id}'. + * @param {string} vnode.attrs.classes The CSS classes to be applied to the copy button. + * @param {string} vnode.attrs.style The inline styles to be applied to the copy button. + * @param {function} vnode.attrs.onFailure The callback function to be invoked if copying to the clipboard fails. * @returns {Component} The copyToClipboard button component */ view(vnode) { const { attrs, children } = vnode; - const { value: clipboardTargetValue = '', id } = attrs; + // Attributes other than those listed are not forwarded to the button element + const { value: clipboardTargetValue = '', id, className = 'btn-primary', style, onFailure } = attrs; let available = true; let message = ''; @@ -104,14 +122,16 @@ export class CopyToClipboardComponent extends StatefulComponent { const successContent = [iconCheck(), h('', 'Copied!')]; return h( - 'button.btn.btn-primary', + 'button.btn', { id: `copy-${id}`, - onclick: () => this.copyToClipboard(clipboardTargetValue), + onclick: () => this.copyToClipboard(clipboardTargetValue, onFailure), disabled: !available, - title: message || null, + title: message || '', + style, + className, }, - h('div.flex-row.g1', this._successStateTimeout ? successContent : defaultContent), + h('div.flex-row.g1.justify-center', { ariaLive: 'polite' }, this._successStateTimeout ? successContent : defaultContent), ); } }