Trello如何访问用户的剪贴板?
当您将鼠标hover在Trello中的卡片上并按Ctrl + C时 ,此卡片的URL将被复制到剪贴板。 他们如何做到这一点?
据我所知,没有涉及的Flash电影。 我已经安装了Flashblock ,并且Firefoxnetworking选项卡显示没有加载Flash电影。 (这是通常的方法,例如,ZeroClipboard。)
他们如何实现这个魔法?
(在这一刻,我想我有一个顿悟:你不能select页面上的文本,所以我假设他们有一个不可见的元素,他们通过JavaScript代码创build一个文本select, Ctrl + C触发浏览器的默认行为,复制那个看不见的节点的文本值。)
披露: 我写了Trello使用的代码 ; 下面的代码是Trello用来完成剪贴板技巧的实际源代码。
我们实际上并不是“访问用户的剪贴板”,而是通过按Ctrl + C来select一些有用的东西来帮助用户。
听起来你已经知道了; 我们利用这个事实,即当你想按Ctrl + C时 ,你必须先按下Ctrl键。 当按下Ctrl键时,我们popup一个包含我们想要在剪贴板上结束的文本的textarea,并select其中的所有文本,所以当C键被击中时,所有的select都被设置。 (然后当Ctrl键出现时我们隐藏textarea)
具体来说,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这样做,所以你不能真正看到textarea时,它popup…但它是“可见的”足以复制。
当你将鼠标hover在卡上时,它会调用
TrelloClipboard.set(cardUrl)
…所以然后剪贴板助手知道按下Ctrl键时要select什么。
我实际上构build了一个Chrome扩展 ,完成了这一切,并为所有的网页。 源代码在GitHub上 。
我发现Trello的方法有三个错误,我知道是因为我自己面对过他们:)
该副本在这些情况下不起作用:
- 如果您已经按下Ctrl键,然后hover一个链接并点击C ,副本不起作用。
- 如果您的光标位于页面的其他文本字段中,则复制不起作用。
- 如果您的光标在地址栏中,则复制不起作用。
我解决了#1总是有一个隐藏的跨度,而不是创build一个当用户点击Ctrl / Cmd 。
我通过暂时清除零长度选项,保存插入位置,复制和恢复插入位置来解决#2问题。
我还没有find#3的修复:)(有关信息,请检查我的GitHub项目中的开放问题)。
在雨衣的( 链接到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中testing了它。 用法与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; })());
缩短url时,可以在http://goo.gl上看到非常相似的内容。;
有一个readonlyinput元素,获取以编程为中心的工具提示“按CTRL-C复制”。 当你点击该快捷方式时,input的内容就会有效地进入剪贴板。 非常好 :)