Pertanyaan Bagaimana cara Trello mengakses papan klip pengguna?


Saat Anda mengarahkan kursor ke kartu Trello dan tekan Ctrl+C, URL kartu ini disalin ke papan klip. bagaimana mereka melakukan ini?

Sejauh yang saya tahu, tidak ada film Flash yang terlibat. aku mendapat Flashblock terinstal, dan tab jaringan Firefox menunjukkan tidak ada film Flash yang dimuat. (Itu metode yang biasa, misalnya, oleh ZeroClipboard.)

Bagaimana mereka mencapai keajaiban ini?

(Tepat pada saat ini saya pikir saya memiliki pencerahan: Anda tidak dapat memilih teks di halaman, jadi saya menganggap mereka memiliki elemen tak terlihat, di mana mereka membuat pilihan teks melalui kode JavaScript, dan Ctrl+C memicu perilaku default browser, menyalin nilai teks node yang tak terlihat itu.)


896
2017-07-08 13:26


asal


Jawaban:


Penyingkapan:  Saya menulis kode yang digunakan oleh Trello; kode di bawah ini adalah kode sumber yang digunakan Trello untuk menyelesaikan trik clipboard.


Kami sebenarnya tidak "mengakses papan klip pengguna", sebagai gantinya kami membantu pengguna keluar sedikit dengan memilih sesuatu yang berguna ketika mereka menekan Ctrl+C.

Kedengarannya seperti Anda sudah mengetahuinya; kami mengambil keuntungan dari fakta bahwa ketika Anda ingin memukul Ctrl+C, Anda harus menekan Ctrl kunci pertama. Ketika Ctrl tombol ditekan, kita pop di textarea yang berisi teks yang kita ingin berakhir di clipboard, dan pilih semua teks di dalamnya, sehingga pilihan sudah siap ketika C kuncinya dipukul. (Kemudian kita menyembunyikan textarea ketika Ctrl kunci muncul)

Secara khusus, Trello melakukan ini:

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) ->

Di DOM kita punya

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

CSS untuk materi clipboard:

#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;
}

... dan CSS membuatnya sehingga Anda tidak dapat benar-benar melihat textarea ketika itu muncul ... tapi cukup "terlihat" untuk disalin.

Saat Anda mengarahkan kartu, panggilan itu

TrelloClipboard.set(cardUrl)

... jadi kemudian helper clipboard tahu apa yang harus dipilih ketika Ctrl tombol ditekan.


1510
2017-07-08 14:00



Saya benar-benar dibangun ekstensi Chrome yang melakukan hal ini, dan untuk semua halaman web. Kode sumbernya di GitHub.

Saya menemukan tiga bug dengan pendekatan Trello, yang saya tahu karena saya telah menghadapi mereka sendiri :)

Salinan tidak berfungsi dalam skenario ini:

  1. Jika sudah ada Ctrl ditekan dan kemudian arahkan tautan dan tekan C, salinannya tidak berfungsi.
  2. Jika kursor Anda ada di beberapa bidang teks lain di halaman, salinannya tidak berfungsi.
  3. Jika kursor Anda ada di bilah alamat, salinannya tidak berfungsi.

Saya memecahkan # 1 dengan selalu memiliki rentang yang tersembunyi, daripada membuat satu ketika hits pengguna Ctrl/Cmd.

Saya menyelesaikan # 2 dengan secara sementara membersihkan seleksi tanpa panjang, menyimpan posisi sisipan, melakukan penyalinan dan memulihkan posisi sisipan.

Saya belum menemukan perbaikan untuk # 3 belum :) (Untuk informasi, periksa masalah terbuka di proyek GitHub saya).


77
2017-08-03 23:01



Dengan bantuan jas hujan (tautan ke GitHub) kode, saya berhasil mendapatkan versi berjalan yang mengakses clipboard dengan JavaScript biasa.

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");

Satu-satunya masalah adalah, bahwa versi ini hanya berfungsi dengan Chrome. Platform Trello mendukung semua browser. Apa yang saya lewatkan?

Terima kasih untuk VadimIvanov.

Lihat contoh kerja: http://jsfiddle.net/AGEf7/


19
2018-01-16 11:03



Kode Daniel LeCheminant tidak berfungsi untuk saya setelah mengonversinya dari CoffeeScript ke JavaScript (js2coffee). Itu terus mengebom pada _.defer() garis.

Saya berasumsi ini ada hubungannya dengan penundaan jQuery, jadi saya mengubahnya menjadi $.Deferred() dan itu berfungsi sekarang. Saya mengujinya di Internet Explorer 11, Firefox 35, dan Chrome 39 dengan jQuery 2.1.1. Penggunaannya sama seperti yang dijelaskan dalam posting Daniel.

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



Sesuatu yang sangat mirip bisa dilihat http://goo.gl ketika Anda mempersingkat URL.

Ada elemen masukan hanya baca yang mendapat fokus terprogram, dengan keterangan alat "Tekan CTRL-C untuk menyalin". Saat Anda menekan pintasan itu, konten masukan secara efektif masuk ke papan klip. Benar-benar bagus :)


5
2017-08-05 20:32