diff --git a/javascript/src/Clipboard.js b/javascript/src/Clipboard.js
new file mode 100644
index 0000000000000000000000000000000000000000..7e5d7ca33f950b622a3eb9912d476da63572083a
--- /dev/null
+++ b/javascript/src/Clipboard.js
@@ -0,0 +1,66 @@
+/* @author Benjamin Baer <benjamin.baer@math.uzh.ch> */
+
+/* global $ */
+/* global EventEmitter */
+/* @depend QfqEvents.js */
+/* @depend Alert.js */
+
+
+var QfqNS = QfqNs || {};
+
+(function (n) {
+
+    n.Clipboard = function (data) {
+        this.copyTextToClipboardAsync(data.text);
+    };
+
+    n.Clipboard.prototype.copyTextToClipboard = function(text) {
+        var textArea = document.createElement("textarea");
+        textArea.value = text;
+        document.body.appendChild(textArea);
+        textArea.focus();
+        textArea.select();
+
+        try {
+            var successful = document.execCommand('copy');
+            var msg = successful ? 'successful' : 'unsuccessful';
+            console.log('Fallback: Copying text command was ' + msg);
+        } catch (err) {
+            this.buildError("Couldn't copy text to clipboard: " + err);
+        }
+
+        document.body.removeChild(textArea);
+    };
+
+    /**
+     * Tries to copy text to the clipboard using asynchronous browser API.
+     * If it doesn't exist, calls copyTextToClipboard (synchronous) instead.
+     * @private String text
+     */
+    n.Clipboard.prototype.copyTextToClipboardAsync = function(text) {
+        if (!navigator.clipboard) {
+            this.fallbackCopyTextToClipboard(text);
+            return;
+        }
+
+        var that = this;
+        navigator.clipboard.writeText(text).then(function() {
+            console.log('Async: Copying to clipboard was successful!');
+        }, function(err) {
+            that.buildError("Could not copy text: " + err);
+        });
+    };
+
+    n.Clipboard.prototype.buildError = function(message) {
+        var alert = new n.Alert(
+            {
+                type: "error",
+                message: message,
+                modal: true,
+                buttons: {label: "Ok", eventName: 'close'}
+            }
+        );
+        alert.show();
+    };
+
+})(QfqNS);