javascript coffeescript clipboard trello

javascript - ¿Cómo accede Trello al portapapeles del usuario?



coffeescript clipboard (5)

Algo muy similar se puede ver en http://goo.gl cuando acorta la URL.

Hay un elemento de entrada de solo lectura que se enfoca programáticamente, con información sobre herramientas "Presione CTRL-C para copiar". Cuando golpea ese acceso directo, el contenido de entrada entra efectivamente en el portapapeles. Muy agradable :)

Cuando se desplaza sobre una tarjeta en Trello y presiona Ctrl + C , la URL de esta tarjeta se copia al portapapeles. ¿Cómo lo hacen?

Por lo que puedo decir, no hay ninguna película Flash involucrada. Tengo instalado Flashblock y la pestaña de red de Firefox no muestra ninguna película Flash cargada. (Ese es el método usual, por ejemplo, por ZeroClipboard).

¿Cómo logran esta magia?

(Justo en este momento, creo que tuve una revelación: no puede seleccionar texto en la página, así que asumo que tienen un elemento invisible, donde crean una selección de texto a través de un código JavaScript, y Ctrl + C activa el comportamiento predeterminado del navegador, copiando el valor de texto de ese nodo invisible.)


Con la ayuda del código de Raincoat ( enlace a GitHub ), conseguí una versión en ejecución para acceder al portapapeles con JavaScript plano.

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

El único problema es que esta versión solo funciona con Chrome. La plataforma Trello soporta todos los navegadores. ¿Qué me estoy perdiendo?

Gracias gracias a VadimIvanov.

Vea un ejemplo de trabajo: http://jsfiddle.net/AGEf7/


El código de Daniel LeCheminant no me funcionó después de convertirlo de CoffeeScript a JavaScript ( js2coffee.org ). Se mantuvo bombardeando en la línea _.defer() .

Asumí que esto tenía algo que ver con los aplazados de jQuery, así que lo cambié a $.Deferred() y ahora está funcionando. Lo probé en Internet Explorer 11, Firefox 35 y Chrome 39 con jQuery 2.1.1. El uso es el mismo que se describe en la publicación de 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; })());


Realmente construí una extensión de Chrome que hace exactamente esto, y para todas las páginas web. El código fuente está en GitHub .

Encuentro tres errores con el enfoque de Trello, que conozco porque los enfrenté yo mismo :)

La copia no funciona en estos escenarios:

  1. Si ya tienes presionado Ctrl y luego pasas el mouse sobre un enlace y presionas C , la copia no funciona.
  2. Si su cursor está en algún otro campo de texto en la página, la copia no funciona.
  3. Si su cursor está en la barra de direcciones, la copia no funciona.

Resolví el # 1 teniendo siempre un intervalo oculto, en lugar de crear uno cuando el usuario pulsa Ctrl / Cmd .

Resolví el # 2 borrando temporalmente la selección de longitud cero, guardando la posición de intercalación, haciendo la copia y restaurando la posición de intercalación.

Todavía no he encontrado una solución para el # 3 :) (Para obtener información, consulte el tema abierto en mi proyecto de GitHub).


Divulgación: escribí el código que usa Trello ; El código a continuación es el código fuente real que Trello usa para lograr el truco del portapapeles.

En realidad, no "accedemos al portapapeles del usuario", en su lugar ayudamos al usuario un poco seleccionando algo útil cuando presionan Ctrl + C.

Parece que lo has descubierto; Aprovechamos el hecho de que cuando desea presionar Ctrl + C , primero debe presionar la tecla Ctrl . Cuando se presiona la tecla Ctrl, aparece un área de texto que contiene el texto que queremos que termine en el portapapeles, y seleccionamos todo el texto en él, por lo que la selección se establece cuando se presiona la tecla C. (Luego escondemos el área de texto cuando aparece la tecla Ctrl )

Específicamente, Trello hace esto:

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

En el DOM tenemos

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

CSS para las cosas del portapapeles:

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

... y el CSS lo hace así que realmente no se puede ver el área de texto cuando aparece ... pero es lo suficientemente "visible" para copiarlo.

Cuando se pasa sobre una tarjeta, llama

TrelloClipboard.set(cardUrl)

... entonces el asistente del portapapeles sabe qué seleccionar cuando se presiona la tecla Ctrl .