From 95df7e5e6cac00fe38194990ed737c1d8cf30bb5 Mon Sep 17 00:00:00 2001 From: Nurhan Turgut Date: Tue, 14 Jan 2020 16:31:45 -0800 Subject: [PATCH 1/5] clipboard support with range --- lib/web_ui/lib/src/engine/clipboard.dart | 54 +++++++++++++++++++++--- 1 file changed, 47 insertions(+), 7 deletions(-) diff --git a/lib/web_ui/lib/src/engine/clipboard.dart b/lib/web_ui/lib/src/engine/clipboard.dart index d7c462cea7e0a..35f260f35f244 100644 --- a/lib/web_ui/lib/src/engine/clipboard.dart +++ b/lib/web_ui/lib/src/engine/clipboard.dart @@ -36,9 +36,10 @@ class ClipboardMessageHandler { /// APIs and the browser. abstract class CopyToClipboardStrategy { factory CopyToClipboardStrategy() { - return (html.window.navigator.clipboard.writeText != null) - ? ClipboardAPICopyStrategy() - : ExecCommandCopyStrategy(); + return ExecCommandCopyStrategy(); + // return (html.window.navigator.clipboard?.writeText != null) + // ? ClipboardAPICopyStrategy() + // : ExecCommandCopyStrategy(); } /// Places the text onto the browser Clipboard. @@ -52,7 +53,7 @@ abstract class CopyToClipboardStrategy { abstract class PasteFromClipboardStrategy { factory PasteFromClipboardStrategy() { return (browserEngine == BrowserEngine.firefox || - html.window.navigator.clipboard.readText == null) + html.window.navigator.clipboard?.readText == null) ? ExecCommandPasteStrategy() : ClipboardAPIPasteStrategy(); } @@ -91,9 +92,48 @@ class ClipboardAPIPasteStrategy implements PasteFromClipboardStrategy { class ExecCommandCopyStrategy implements CopyToClipboardStrategy { @override void setData(String text) { - // TODO(nurhan): https://github.com/flutter/flutter/issues/48578 - print('Clipboard is only implemented for browsers ' - 'supporting Clipboard API. Use context menu for text editing.'); + final html.TextAreaElement tempTextArea = _appendTemporaryTextArea(); + tempTextArea.text = text; + + tempTextArea.focus(); + // tempTextArea.select(); + + final html.Range range = html.document.createRange(); + range.selectNode(tempTextArea); + html.window.getSelection().addRange(range); + + try { + final bool result = html.document.execCommand('copy'); + if (!result) { + print('copy is not successful'); + } + } catch (e) { + print('copy is not successful ${e.message}'); + } finally { + html.window.getSelection().removeAllRanges(); + _removeTemporaryTextArea(tempTextArea); + } + } + + html.TextAreaElement _appendTemporaryTextArea() { + final html.TextAreaElement tempElement = html.TextAreaElement(); + final html.CssStyleDeclaration elementStyle = tempElement.style; + elementStyle + ..position = 'absolute' + ..top = '100px' + ..left = '100px' + ..opacity = '0' + ..color = 'transparent' + ..backgroundColor = 'transparent' + ..background = 'transparent'; + + html.document.body.append(tempElement); + + return tempElement; + } + + void _removeTemporaryTextArea(html.HtmlElement element) { + element?.remove(); } } From 382812694edac9bec8a1d71c29d3807effe241bf Mon Sep 17 00:00:00 2001 From: nturgut Date: Wed, 15 Jan 2020 09:14:47 -0800 Subject: [PATCH 2/5] changing the implementation to work on Safari --- lib/web_ui/lib/src/engine/clipboard.dart | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/web_ui/lib/src/engine/clipboard.dart b/lib/web_ui/lib/src/engine/clipboard.dart index 35f260f35f244..2eb828ddab3e6 100644 --- a/lib/web_ui/lib/src/engine/clipboard.dart +++ b/lib/web_ui/lib/src/engine/clipboard.dart @@ -36,10 +36,9 @@ class ClipboardMessageHandler { /// APIs and the browser. abstract class CopyToClipboardStrategy { factory CopyToClipboardStrategy() { - return ExecCommandCopyStrategy(); - // return (html.window.navigator.clipboard?.writeText != null) - // ? ClipboardAPICopyStrategy() - // : ExecCommandCopyStrategy(); + return (html.window.navigator.clipboard?.writeText != null) + ? ClipboardAPICopyStrategy() + : ExecCommandCopyStrategy(); } /// Places the text onto the browser Clipboard. @@ -96,11 +95,12 @@ class ExecCommandCopyStrategy implements CopyToClipboardStrategy { tempTextArea.text = text; tempTextArea.focus(); - // tempTextArea.select(); final html.Range range = html.document.createRange(); - range.selectNode(tempTextArea); + range.selectNodeContents(tempTextArea); + html.window.getSelection().removeAllRanges(); html.window.getSelection().addRange(range); + tempTextArea.setSelectionRange(0, 100000); try { final bool result = html.document.execCommand('copy'); From 76882177dbe7686643b8a2e05f0d7e8e9437667c Mon Sep 17 00:00:00 2001 From: nturgut Date: Wed, 15 Jan 2020 10:23:56 -0800 Subject: [PATCH 3/5] addressing PR comments --- lib/web_ui/lib/src/engine/clipboard.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/web_ui/lib/src/engine/clipboard.dart b/lib/web_ui/lib/src/engine/clipboard.dart index 2eb828ddab3e6..f026a19f56862 100644 --- a/lib/web_ui/lib/src/engine/clipboard.dart +++ b/lib/web_ui/lib/src/engine/clipboard.dart @@ -91,8 +91,10 @@ class ClipboardAPIPasteStrategy implements PasteFromClipboardStrategy { class ExecCommandCopyStrategy implements CopyToClipboardStrategy { @override void setData(String text) { + // Copy content to clipboard with execCommand. + // See: https://developers.google.com/web/updates/2015/04/cut-and-copy-commands final html.TextAreaElement tempTextArea = _appendTemporaryTextArea(); - tempTextArea.text = text; + tempTextArea.value = text; tempTextArea.focus(); From 2a769b0e90e3552db3e97a623ff06e0d824b24d1 Mon Sep 17 00:00:00 2001 From: nturgut Date: Wed, 15 Jan 2020 10:39:03 -0800 Subject: [PATCH 4/5] changing value back to text --- lib/web_ui/lib/src/engine/clipboard.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/web_ui/lib/src/engine/clipboard.dart b/lib/web_ui/lib/src/engine/clipboard.dart index f026a19f56862..6728d6d1f79a4 100644 --- a/lib/web_ui/lib/src/engine/clipboard.dart +++ b/lib/web_ui/lib/src/engine/clipboard.dart @@ -94,7 +94,8 @@ class ExecCommandCopyStrategy implements CopyToClipboardStrategy { // Copy content to clipboard with execCommand. // See: https://developers.google.com/web/updates/2015/04/cut-and-copy-commands final html.TextAreaElement tempTextArea = _appendTemporaryTextArea(); - tempTextArea.value = text; + // For `text` See https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent + tempTextArea.text = text; tempTextArea.focus(); From 5b4ed6a8009229ce371b990cbd6599f7f22feae7 Mon Sep 17 00:00:00 2001 From: nturgut Date: Wed, 15 Jan 2020 11:00:29 -0800 Subject: [PATCH 5/5] when textarea.value is used select was also working --- lib/web_ui/lib/src/engine/clipboard.dart | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/lib/web_ui/lib/src/engine/clipboard.dart b/lib/web_ui/lib/src/engine/clipboard.dart index 6728d6d1f79a4..1fbe4a0be1052 100644 --- a/lib/web_ui/lib/src/engine/clipboard.dart +++ b/lib/web_ui/lib/src/engine/clipboard.dart @@ -94,17 +94,9 @@ class ExecCommandCopyStrategy implements CopyToClipboardStrategy { // Copy content to clipboard with execCommand. // See: https://developers.google.com/web/updates/2015/04/cut-and-copy-commands final html.TextAreaElement tempTextArea = _appendTemporaryTextArea(); - // For `text` See https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent - tempTextArea.text = text; - + tempTextArea.value = text; tempTextArea.focus(); - - final html.Range range = html.document.createRange(); - range.selectNodeContents(tempTextArea); - html.window.getSelection().removeAllRanges(); - html.window.getSelection().addRange(range); - tempTextArea.setSelectionRange(0, 100000); - + tempTextArea.select(); try { final bool result = html.document.execCommand('copy'); if (!result) { @@ -113,7 +105,6 @@ class ExecCommandCopyStrategy implements CopyToClipboardStrategy { } catch (e) { print('copy is not successful ${e.message}'); } finally { - html.window.getSelection().removeAllRanges(); _removeTemporaryTextArea(tempTextArea); } } @@ -123,8 +114,8 @@ class ExecCommandCopyStrategy implements CopyToClipboardStrategy { final html.CssStyleDeclaration elementStyle = tempElement.style; elementStyle ..position = 'absolute' - ..top = '100px' - ..left = '100px' + ..top = '-99999px' + ..left = '-99999px' ..opacity = '0' ..color = 'transparent' ..backgroundColor = 'transparent'