[javascript] 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. 커서가 주소 표시 줄에 있으면 사본이 작동하지 않습니다.

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

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

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


답변

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/


답변

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;

})());


답변

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

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

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


답변