Frage Wie greift Trello auf die Zwischenablage des Benutzers zu?


Wenn Sie mit der Maus über eine Karte in Trello und drücke Strg+C, die URL dieser Karte wird in die Zwischenablage kopiert. Wie machen sie das?

Soweit ich das beurteilen kann, gibt es keinen Flash-Film. ich habe Flashblock installiert, und die Registerkarte Firefox-Netzwerk zeigt keinen geladenen Flash-Film. (Dies ist die übliche Methode, z. B. von ZeroClipboard.)

Wie erreichen sie diese Magie?

(Genau in diesem Moment denke ich hatte ich eine Offenbarung: Sie können keinen Text auf der Seite auswählen, also nehme ich an, dass sie ein unsichtbares Element haben, wo sie eine Textauswahl mittels JavaScript-Code erstellen, und Strg+C löst das Standardverhalten des Browsers aus und kopiert den Textwert des unsichtbaren Knotens.)


896
2017-07-08 13:26


Ursprung


Antworten:


Offenlegung:  Ich habe den Code geschrieben, den Trello benutzt; Der Code unten ist der eigentliche Quellcode, den Trello verwendet, um den Zwischenablage-Trick zu erreichen.


Tatsächlich "greifen wir nicht auf die Zwischenablage des Benutzers zu", stattdessen helfen wir dem Benutzer ein wenig, indem er etwas Nützliches auswählt, wenn er drückt Strg+C.

Hört sich an, als hättest du es herausgefunden; Wir nutzen die Tatsache, dass wenn Sie treffen wollen Strg+C, du musst die Strg Schlüssel zuerst. Wenn das Strg Wenn Sie die Taste drücken, wird ein Textbereich angezeigt, der den Text enthält, der in der Zwischenablage angezeigt werden soll, und Sie können den gesamten darin enthaltenen Text auswählen C Schlüssel ist getroffen. (Dann verstecken wir das Textfeld, wenn der Strg Schlüssel kommt auf)

Genauer gesagt, Trello macht das:

TrelloClipboard = new class
  constructor: ->
    @value = ""

    $(document).keydown (e) =>
      # Only do this if there's something to be put on the clipboard, and it
      # looks like they're starting a copy shortcut
      if !@value || !(e.ctrlKey || e.metaKey)
        return

      if $(e.target).is("input:visible,textarea:visible")
        return

      # Abort if it looks like they've selected some text (maybe they're trying
      # to copy out a bit of the description or something)
      if window.getSelection?()?.toString()
        return

      if document.selection?.createRange().text
        return

      _.defer =>
        $clipboardContainer = $("#clipboard-container")
        $clipboardContainer.empty().show()
        $("<textarea id='clipboard'></textarea>")
        .val(@value)
        .appendTo($clipboardContainer)
        .focus()
        .select()

    $(document).keyup (e) ->
      if $(e.target).is("#clipboard")
        $("#clipboard-container").empty().hide()

  set: (@value) ->

Im DOM haben wir

<div id="clipboard-container"><textarea id="clipboard"></textarea></div>

CSS für die Zwischenablage:

#clipboard-container {
  position: fixed;
  left: 0px;
  top: 0px;
  width: 0px;
  height: 0px;
  z-index: 100;
  display: none;
  opacity: 0;
}
#clipboard {
  width: 1px;
  height: 1px;       
  padding: 0px;
}

... und das CSS macht es so, dass man das Textfeld nicht sehen kann, wenn es erscheint ... aber es ist "sichtbar" genug, um es zu kopieren.

Wenn Sie mit der Maus über eine Karte fahren, wird sie angerufen

TrelloClipboard.set(cardUrl)

... also dann weiß der Zwischenablage-Helfer, was zu wählen ist, wenn der Strg Taste wird gedrückt.


1510
2017-07-08 14:00



Ich habe es gebaut eine Chrome-Erweiterung das macht genau das und für alle Webseiten. Der Quellcode ist auf GitHub.

Ich finde drei Fehler mit Trellos Vorgehensweise, die ich kenne, weil ich sie selbst getroffen habe :)

Die Kopie funktioniert in diesen Szenarien nicht:

  1. Wenn du schon hast Strg gedrückt und dann einen Link halten und drücken C, die Kopie funktioniert nicht.
  2. Wenn sich der Cursor in einem anderen Textfeld auf der Seite befindet, funktioniert die Kopie nicht.
  3. Wenn sich der Cursor in der Adressleiste befindet, funktioniert die Kopie nicht.

Ich habe # 1 gelöst, indem ich immer eine versteckte Spanne hatte, anstatt eine zu erstellen, wenn der Benutzer trifft Strg/Befrage.

Ich löste # 2, indem ich die Zero-Length-Auswahl vorübergehend löschte, die Caret-Position speicherte, die Kopie erstellte und die Caret-Position wiederherstellte.

Ich habe noch keinen Fix für # 3 gefunden :) (Für Informationen, überprüfen Sie das offene Problem in meinem GitHub-Projekt).


77
2017-08-03 23:01



Mit Hilfe von Regenmänteln (Link zu GitHub) Code, ich habe es geschafft, eine laufende Version zu bekommen, die mit Klartext JavaScript auf die Zwischenablage zugreift.

function TrelloClipboard() {
    var me = this;

    var utils = {
        nodeName: function (node, name) {
            return !!(node.nodeName.toLowerCase() === name)
        }
    }
    var textareaId = 'simulate-trello-clipboard',
        containerId = textareaId + '-container',
        container, textarea

    var createTextarea = function () {
        container = document.querySelector('#' + containerId)
        if (!container) {
            container = document.createElement('div')
            container.id = containerId
            container.setAttribute('style', [, 'position: fixed;', 'left: 0px;', 'top: 0px;', 'width: 0px;', 'height: 0px;', 'z-index: 100;', 'opacity: 0;'].join(''))
            document.body.appendChild(container)
        }
        container.style.display = 'block'
        textarea = document.createElement('textarea')
        textarea.setAttribute('style', [, 'width: 1px;', 'height: 1px;', 'padding: 0px;'].join(''))
        textarea.id = textareaId
        container.innerHTML = ''
        container.appendChild(textarea)

        textarea.appendChild(document.createTextNode(me.value))
        textarea.focus()
        textarea.select()
    }

    var keyDownMonitor = function (e) {
        var code = e.keyCode || e.which;
        if (!(e.ctrlKey || e.metaKey)) {
            return
        }
        var target = e.target
        if (utils.nodeName(target, 'textarea') || utils.nodeName(target, 'input')) {
            return
        }
        if (window.getSelection && window.getSelection() && window.getSelection().toString()) {
            return
        }
        if (document.selection && document.selection.createRange().text) {
            return
        }
        setTimeout(createTextarea, 0)
    }

    var keyUpMonitor = function (e) {
        var code = e.keyCode || e.which;
        if (e.target.id !== textareaId || code !== 67) {
            return
        }
        container.style.display = 'none'
    }

    document.addEventListener('keydown', keyDownMonitor)
    document.addEventListener('keyup', keyUpMonitor)
}

TrelloClipboard.prototype.setValue = function (value) {
    this.value = value;
}

var clip = new TrelloClipboard();
clip.setValue("test");

Das einzige Problem ist, dass diese Version nur mit Chrome funktioniert. Die Trello-Plattform unterstützt alle Browser. Was ich vermisse?

Sovled dank Vadim Ivanov.

Siehe ein Arbeitsbeispiel: http://jsfiddle.net/AGEf7/


19
2018-01-16 11:03



Der Code von Daniel LeCheminant funktionierte für mich nicht, nachdem ich ihn von CoffeeScript in JavaScript umgewandelt hatte (js2kaffee). Es bombardierte weiter auf der _.defer() Linie.

Ich nahm an, dass dies etwas mit jQuery Deferreds zu tun hatte, also habe ich es in geändert $.Deferred() und es funktioniert jetzt. Ich habe es in Internet Explorer 11, Firefox 35 und Chrome 39 mit jQuery 2.1.1 getestet. Die Verwendung ist die gleiche wie in Daniels Beitrag beschrieben.

var TrelloClipboard;

TrelloClipboard = new ((function () {
    function _Class() {
        this.value = "";
        $(document).keydown((function (_this) {
            return function (e) {
                var _ref, _ref1;
                if (!_this.value || !(e.ctrlKey || e.metaKey)) {
                    return;
                }
                if ($(e.target).is("input:visible,textarea:visible")) {
                    return;
                }
                if (typeof window.getSelection === "function" ? (_ref = window.getSelection()) != null ? _ref.toString() : void 0 : void 0) {
                    return;
                }
                if ((_ref1 = document.selection) != null ? _ref1.createRange().text : void 0) {
                    return;
                }
                return $.Deferred(function () {
                    var $clipboardContainer;
                    $clipboardContainer = $("#clipboard-container");
                    $clipboardContainer.empty().show();
                    return $("<textarea id='clipboard'></textarea>").val(_this.value).appendTo($clipboardContainer).focus().select();
                });
            };
        })(this));

        $(document).keyup(function (e) {
            if ($(e.target).is("#clipboard")) {
                return $("#clipboard-container").empty().hide();
            }
        });
    }

    _Class.prototype.set = function (value) {
        this.value = value;
    };

    return _Class;

})());

7
2018-01-18 00:22



Etwas sehr ähnliches kann auf gesehen werden http://goo.gl wenn Sie die URL kürzen.

Es gibt ein readonly-Eingabeelement, das programmgesteuert fokussiert wird, mit dem Tooltip "Drücken Sie STRG-C zum Kopieren". Wenn Sie auf diese Verknüpfung klicken, wird der Eingabeinhalt effektiv in die Zwischenablage übertragen. Wirklich nett :)


5
2017-08-05 20:32