UNPKG

@eclipse-scout/core

Version:
151 lines (137 loc) 5.15 kB
/* * Copyright (c) 2010, 2025 BSI Business Systems Integration AG * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 */ import {DesktopNotification, FocusRule, scout, Session, Status, Widget} from '../index'; import $ from 'jquery'; export interface ClipboardTextCopyOptions { /** * The text to write to the clipboard. */ text: string; /** * Widget that wants to copy the text. Recommended. * Used to retrieve the session and the document. */ parent?: Widget; /** * Scout session object, used to resolve texts and access the focus manager. Only required when "parent" is not set. */ session?: Session; /** * If true, a desktop notification is shown when copying has been completed. Requires the "parent" option to be present. * If this is true, the {@link copyText} method returns null. Otherwise, it returns a promise that is resolved or rejected when the copying is complete. */ showNotification?: boolean; } export const clipboard = { /** * Copies the given text to the clipboard. To make this work, the method must be called inside * a "user action" (i.e. mouse or keyboard event handler). For security reasons, the access to * the clipboard is blocked by the browser in other contexts (e.g. asynchronous callbacks). * * @param options mandatory * @returns a promise or null if {@link options.showNotification} is true. */ copyText(options: ClipboardTextCopyOptions): JQuery.Promise<void> { scout.assertParameter('options', options); if (options.parent && !options.session) { options.session = options.parent.session; } scout.assertProperty(options, 'session'); let promise = clipboard._copyText(options); if (options.parent && scout.nvl(options.showNotification, true)) { clipboard._showNotification(options, promise); return null; } return promise; }, /** @internal */ _copyText(options: ClipboardTextCopyOptions): JQuery.Promise<void> { let deferred = $.Deferred(); // Modern clipboard API // https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API let win = options?.parent?.window(true) || window; if (win.navigator.clipboard) { win.navigator.clipboard.writeText(options.text) .then((...args) => deferred.resolve(...args)) .catch((...args) => deferred.reject(...args)); return deferred.promise(); } // Fallback for browsers that don't support the modern clipboard API (IE, Safari, Chrome < 66, Firefox < 63) // Create invisible textarea field and use document command "copy" to copy the text to the clipboard let doc = options?.parent?.document(true) || document; let f = doc.createElement('textarea'); f.style.position = 'fixed'; f.style.opacity = '0.0'; f.value = options.text; doc.body.appendChild(f); // Preserve focus let $f = $(f); options.session.focusManager.installFocusContext($f, FocusRule.AUTO); f.select(); // cannot use jquery select(), because that is overridden by jquery-scout try { let successful = doc.execCommand('copy'); if (successful) { deferred.resolve(); } else { deferred.reject(); } } catch (err) { deferred.reject(err); } finally { // Restore focus options.session.focusManager.uninstallFocusContext($f); doc.body.removeChild(f); } return deferred.promise(); }, /** @internal */ _showNotification(options: ClipboardTextCopyOptions, promise: JQuery.Promise<void>) { let status = clipboard._successStatus(options.parent.session); promise .catch(() => { status = clipboard._failedStatus(options.parent.session); }) .then(() => { clipboard.showNotification(options.parent, status); }); }, /** @internal */ _successStatus(session: Session): Status { return new Status({ message: session.text('ui.CopyToClipboardSuccessStatus'), severity: Status.Severity.INFO }); }, /** @internal */ _failedStatus(session: Session): Status { return new Status({ message: session.text('ui.CopyToClipboardFailedStatus'), severity: Status.Severity.WARNING }); }, /** * Shows a short desktop notification. By default, it informs the user that the content * has been copied to the clipboard successfully. By passing a different status, the * message can be changed. * * @param parent Widget that wants to show the notification. Mandatory. Required for NLS texts. */ showNotification(parent: Widget, status?: Status) { scout.assertParameter('parent', parent); status = status || clipboard._successStatus(parent.session); let notification = scout.create(DesktopNotification, { parent: parent, closable: false, duration: status.isValid() ? 1234 : 3456, // use longer duration for errors because error message is longer status: status }); notification.show(); } };