developer tip

Trello는 사용자의 클립 보드에 어떻게 액세스하나요?

optionbox 2020. 9. 28. 09:01
반응형

Trello는 사용자의 클립 보드에 어떻게 액세스하나요?


Trello 에서 카드 위로 마우스를 가져간 다음 Ctrl+를 누르면 C이 카드의 URL이 클립 보드에 복사됩니다. 그들은 이것을 어떻게합니까?

내가 알 수있는 한, Flash 무비는 포함되어 있지 않습니다. 내가있어 Flashblock을이 설치하고, 파이어 폭스 네트워크 탭 쇼에는 플래시 동영상이로드되지 않습니다. (예를 들어 ZeroClipboard의 일반적인 방법입니다.)

그들은이 마법을 어떻게 성취합니까?

(이 순간 나는 깨달음이 있다고 생각합니다. 페이지에서 텍스트를 선택할 수 없으므로 JavaScript 코드를 통해 텍스트 선택을 생성하는 보이지 않는 요소가 있다고 가정하고 Ctrl+ C는 브라우저의 기본 동작을 트리거하여 보이지 않는 것을 복사합니다. 노드의 텍스트 값.)


공개 : Trello가 사용하는 코드를 작성했습니다 . 아래 코드는 Trello가 클립 보드 트릭을 수행하는 데 사용하는 실제 소스 코드입니다.


우리는 실제로 "사용자의 클립 보드에 액세스"하는 것이 아니라 사용자가 Ctrl+ 를 누를 때 유용한 것을 선택하여 약간의 도움을줍니다 C.

당신이 알아 낸 것 같네요. 우리는 당신이 공격 할 때 사실을 활용 Ctrl+ C, 당신이 공격 할 Ctrl첫 번째 키를. Ctrl키를 누르면됩니다 때 선택이 모든 설정 그래서, 우리는 우리가 클립 보드에 결국 할 텍스트가 포함 된 텍스트 영역에 팝업, 그리고 모든 텍스트를 선택 C키를 맞았다. (그런 다음 Ctrl키가 나타나면 텍스트 영역을 숨 깁니다 )

특히 Trello는 다음을 수행합니다.

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

DOM에서 우리는

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

클립 보드 관련 CSS :

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

... 그리고 CSS는 텍스트 영역이 튀어 나왔을 때 실제로 볼 수 없도록 만들어줍니다. ...하지만 복사 할만큼 충분히 "표시"됩니다.

카드 위로 마우스를 가져 가면

TrelloClipboard.set(cardUrl)

... 그러면 클립 보드 도우미는 Ctrl키를 누를 때 무엇을 선택해야하는지 알게됩니다 .


저는 실제로 모든 웹 페이지에 대해 정확히이 작업을 수행 하는 Chrome 확장 프로그램만들었 습니다 . 소스 코드는 GitHub에 있습니다 .

Trello의 접근 방식에서 세 가지 버그를 발견했습니다. 내가 직접 직면했기 때문에 알고 있습니다. :)

다음 시나리오에서는 사본이 작동하지 않습니다.

  1. 이미 Ctrl눌렀다가 링크를 가리키고를 누르면 C복사가 작동하지 않습니다.
  2. 커서가 페이지의 다른 텍스트 필드에 있으면 복사가 작동하지 않습니다.
  3. If your cursor is in the address bar, the copy doesn't work.

I solved #1 by always having a hidden span, rather than creating one when user hits Ctrl/Cmd.

I solved #2 by temporarily clearing the zero-length selection, saving the caret position, doing the copy and restoring the caret position.

I haven't found a fix for #3 yet :) (For information, check the open issue in my GitHub project).


With the help of raincoat's (link to GitHub) code, I managed to get a running version accessing the clipboard with plain JavaScript.

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

The only problem is, that this version only works with Chrome. The Trello platform supports all browsers. What I am missing?

Sovled thanks to VadimIvanov.

See a working example: http://jsfiddle.net/AGEf7/


Daniel LeCheminant's code didn't work for me after converting it from CoffeeScript to JavaScript (js2coffee). It kept bombing out on the _.defer() line.

I assumed this was something to do with jQuery deferreds, so I changed it to $.Deferred() and it's working now. I tested it in Internet Explorer 11, Firefox 35, and Chrome 39 with jQuery 2.1.1. The usage is the same as described in Daniel's post.

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;

})());

Something very similar can be seen on http://goo.gl when you shorten the URL.

There is a readonly input element that gets programmatically focused, with tooltip "Press CTRL-C to copy". When you hit that shortcut, the input content effectively gets into the clipboard. Really nice :)

참고URL : https://stackoverflow.com/questions/17527870/how-does-trello-access-the-users-clipboard

반응형