Trello는 사용자의 클립 보드에 어떻게 액세스합니까?


936

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

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

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

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


22
라이브 DOM을 보면 클래스가 "clipboard-container"인 div가 있습니다. Ctrl 키를 누르고 있으면 텍스트 영역이 채워집니다 (Ctrl 키를 떼면 제거됩니다). 나는 당신의 주현절이 정확하다고 가정합니다. 카드 당 URL을 어디에 저장하고 있는지 정확히 모르겠습니다.
Ian

@Ian, 예, 확인할 수 있습니다. 그것이 정확히 작동하는 방식입니다. 그것을 파고 주셔서 감사합니다! (URL이 저장된 위치는 신경 쓰지 않습니다. 플래시 기술이없는 클립 보드에 관심이있었습니다.)
Boldewyn

2
나는 Daniel의 프로필을 봤는데, 그는 Trello 개발자 인 것 같습니다. (나는 그가 Coffeescript 출처를 어디에서 얻었는지 궁금했다.) 그래서 그는 부당한 이점을 가지고있다.
Boldewyn

1
나는이 기술의 수완을 방해하지 않을 것이다. 그것은 매우 영리하다. 그러나 나는 이것이 기껏해야 공개 / 문서화가 잘 안되어 있고 최악의 경우 사용자 경험이 매우 좋지 않다고 생각합니다. 물론, 실수로 카드 URL을 복사 한 시간을 기억할 수 없기 때문에 침략적으로 부끄러워하지는 않지만 오랜 Trello 사용자는 이것이 존재하는지 전혀 몰랐습니다.
Michael Wales

3
@MichaelWales이 기능은 5 일 전에 추가되었습니다. 우리는 여전히 그것을 테스트하고 있으며 작동하는 것 같으면 키보드 단축키로 문서화됩니다.
Daniel LeCheminant

답변:


1547

공개 : 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키를 누를 때 무엇을 선택해야하는지 알게됩니다 .


3
대박! 그러나 어떻게 Mac OS를 사용합니까? 거기에서 Command 키를 "들으십시오"?
Suman

28
붙여 넣은 내용을 캡처 할 때도 비슷한 방법이 효과적이라는 점은 주목할 가치가 있습니다.
Michael Robinson

17
키보드 사용자에게는 좋지 않은 것처럼 들립니다. 복사 (또는 다른 창에서 열려면 Ctrl + 클릭하거나 검색하려면 Ctrl + F 등) 할 때마다 포커스가 관련이없는 곳으로 이동합니다.
Adam A

2
+1. 이 답변에서 많은 깔끔한 것들이 진행되고 있습니다. 나는 당신이 실제로 소스 코드를 공유 한 것을 좋아합니다. 그러나 내가 영리하다고 생각한 것은 ctrl + c 기능을 제공하는 데 사용되는 프로세스에 대한 실제 설명이었습니다. 제 생각에는 Ctrl 키를 누를 때 c를 준비하기 시작하면 ctrl 키와 c 키를 동시에 누를 수 없다는 사실을 활용하는 것이 매우 영리했습니다. 나는 그 접근법을 정말로 좋아했다.
Travis J

8
원한다면 js2coffee.org 를 사용 하여 원본을 js로 번역하십시오.
Alexandr Kurilin

79

실제로 정확히 모든 웹 페이지와이를위한 Chrome 확장 프로그램 을 구축 했습니다 . 소스 코드는 GitHub에 있습니다 .

Trello의 접근 방식으로 세 가지 버그를 발견했습니다.

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

  1. 이미 Ctrl링크를 누른 다음 링크를 가리키고를 누르면 C복사가 작동하지 않습니다.
  2. 커서가 페이지의 다른 텍스트 필드에 있으면 복사가 작동하지 않습니다.
  3. 커서가 주소 표시 줄에 있으면 사본이 작동하지 않습니다.

사용자가 Ctrl/를 칠 때 항상 범위를 만들지 않고 숨겨진 범위를 유지하여 # 1을 해결했습니다 Cmd.

길이가 0 인 선택을 일시적으로 지우고 캐럿 위치를 저장하고 복사를 수행하고 캐럿 위치를 복원하여 # 2를 해결했습니다.

아직 # 3에 대한 해결책을 찾지 못했습니다 :) (자세한 내용은 GitHub 프로젝트에서 공개 된 문제를 확인하십시오).


10
실제로 Trello와 같은 방식으로이 작업을 수행했습니다. 그러한 것들이 수렴 할 때 달콤한
Thomas Ahle

@ThomasAhle, 무슨 뜻인가요?
Pacerier

7
@Pacerier, 나는 토마스가 언급 가정 수렴 진화 "... 서로 다른 계통의 종에서 비슷한 기능의 독립적 인 진화"-
yoniLavi

거룩한 암소 당신은이 주제에 대해 새로운 대화를 열 수 있습니다
carkod

20

raincoat ( GitHub 링크 ) 코드를 사용하여 일반 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");

유일한 문제는이 버전이 Chrome에서만 작동한다는 것입니다. Trello 플랫폼은 모든 브라우저를 지원합니다. 내가 무엇을 놓치고 있습니까?

VadimIvanov에게 감사드립니다.

실제 예제를 참조하십시오 : http://jsfiddle.net/AGEf7/


@ don41382 Safari (적어도 Mac 버전)에서는 제대로 작동하지 않습니다. 적절하게는 복사를 의미하지만 cmd + C를 두 번 눌러야합니다.
Vadim Ivanov

@VadimIvanov True! 누군가 이유를 알고 있습니까?
Felix

1
@ don41382 왜 그런지 정확히 모르겠지만 해결책을 찾았습니다. 사소한 버그가 있습니다. onKeyDown 첫 번째 문장은 if (! (e.ctrlKey || e.metaKey)) {return; } 이것은 metaKey를 눌렀을 때 텍스트 영역을 준비해야 함을 의미합니다 (이것이 trello의 사람들이 트릭을 만든 방식입니다). 이것은 trello.com의 코드입니다. gist.github.com/fustic/10870311
Vadim Ivanov

@VadimIvanov 감사합니다. 위에서 수정하겠습니다.
Felix

1
FF 33.1에서는 el.innerText정의되지 않았기 때문에 작동하지 않았으므로 더 많은 브라우저 간 호환성 clipboard()clip.setValue(el.innerText || el.textContent);위해 함수 의 마지막 줄을 변경했습니다 . 링크 : jsfiddle.net/AGEf7/31
RevanProdigalKnight

7

Daniel LeCheminant의 코드가 CoffeeScript에서 JavaScript ( js2coffee ) 로 변환 된 후에는 작동하지 않았습니다 . _.defer()라인 에서 폭격을 계속했다 .

나는 이것이 jQuery 지연과 관련이 있다고 가정 했으므로로 변경 $.Deferred()했으며 현재 작동 중입니다. jQuery 2.1.1을 사용하여 Internet Explorer 11, Firefox 35 및 Chrome 39에서 테스트했습니다. 사용법은 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;

})());

5

http://goo.gl 에서 매우 비슷한 것을 볼 수 있습니다URL을 줄이면 .

툴팁을 눌러 프로그래밍 방식으로 초점을 맞춘 읽기 전용 입력 요소가 있습니다. CTRL-C 복사 있습니다.

바로 가기를 누르면 입력 내용이 클립 보드에 효과적으로 표시됩니다. 정말 좋은 :)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.