简体   繁体   English

将文本从书签复制到剪贴板

[英]Copy text to clipboard from bookmarklet

I'm trying to write a little bookmarklet that can extract some text from the active page and load that into the clipboard.我正在尝试编写一个小书签,它可以从活动页面中提取一些文本并将其加载到剪贴板中。

The extraction is easy enough, but I'm really stuck doing the clipboard-copying part.提取很容易,但我真的坚持做剪贴板复制部分。 Currently, I'm just alert ing the text and hitting Ctrl + C to copy the text from the message-box, which isn't ideal.目前,我只是alert文本并按Ctrl + C从消息框中复制文本,这并不理想。

I've read How to Copy to Clipboard in JavaScript and other questions that suggest I use zeroclipboard , but I have no idea how one would make that work from a bookmarklet , considering I have to load external flash and javascript resources to be able to use the library.我已经阅读了如何在 JavaScript 中复制到剪贴板和其他建议我使用zeroclipboard 的问题,但我不知道如何从书签中完成这项工作,因为我必须加载外部Flash 和 javascript 资源才能使用图书馆。

I have no issues with messing up the page's DOM to accomplish this or having to enable some permissions on my browser (Google Chrome), considering this is just a private bookmarklet.考虑到这只是一个私人书签,我对搞乱页面的 DOM 以完成此操作或必须在我的浏览器(谷歌浏览器)上启用某些权限没有任何问题。

Any pointers would be appreciated.任何指针将不胜感激。

There is a nice little bookmarket in Github Gist that does the core of what you want -- copying to the clipboard. Github Gist 中有一个不错的小书市,可以完成您想要的核心操作——复制到剪贴板。 It does not use any external libraries, which I think of as an advantage.它不使用任何外部库,我认为这是一个优势。

As written, it copies some static text, but toward the bottom it talks about adapting it to other uses, such as copying the page title.正如所写,它复制了一些静态文本,但在底部它谈到将其调整为其他用途,例如复制页面标题。

Since you've stated that 'The extraction is easy enough ...', you should be easily be able to adapt that gist to what you want to do.既然您已经说过“提取很容易……”,那么您应该能够轻松地将该要点调整为您想要做的事情。

I tried the plain vanilla version of the bookmarklet, because I have some static text that I often need to transfer to my clipboard.我尝试了书签的普通版本,因为我有一些静态文本,我经常需要将这些文本传输到剪贴板。 It works very well in Chrome 61 with no modifications.它在 Chrome 61 中运行良好,无需修改。 But make sure you read the comments;但一定要阅读评论; some people have suggestions on getting it to work in other browsers and scenarios.有些人建议让它在其他浏览器和场景中工作。

Here is the code that I tested, already minified and ready to turn into a bookmarklet:这是我测试的代码,已经缩小并准备好变成书签:

javascript:!function(a){var b=document.createElement("textarea"),c=document.getSelection();b.textContent=a,document.body.appendChild(b),c.removeAllRanges(),b.select(),document.execCommand("copy"),c.removeAllRanges(),document.body.removeChild(b)}("Text To Copy");

Gist has the pre-minified code as well. Gist 也有预先缩小的代码。

Since the new Clipboard API , this is easy in browsers that support it:由于新的Clipboard API ,这在支持它的浏览器中很容易:

javascript: navigator.clipboard.writeText('some text from somewhere');null;

Caveat: Any alerts or prompts in your bookmarklet will cause the document to lose focus, and the clipboard API will become unavailable.警告:书签中的任何警报或提示都会导致文档失去焦点,并且剪贴板 API 将不可用。 In that case you need to move focus back into the document before any subsequent clipboard operations will work:在这种情况下,您需要将焦点移回文档,然后才能进行任何后续剪贴板操作:

const oldFocus = document.activeElement; 
/* do popup stuff */
oldFocus.focus(); 
/* do clipboard stuff */

With recent versions of Firefox, interacting with the clipboard via a bookmarklet in general won't work due to missing permissions (see this information for more details).对于最新版本的 Firefox,由于缺少权限,通常无法通过书签与剪贴板进行交互( 有关更多详细信息,请参阅此信息)。 There may be a way, however, to have the bookmarklet display a button, and perform the clipboard interaction in the context of a button-click event handler.然而,可能有一种方法可以让书签显示一个按钮,并在按钮单击事件处理程序的上下文中执行剪贴板交互。

A possibly more straightforward solution is to use a user-script manager, and define your bookmarklet in the form of a user-script that you can activate via a keyboard combination.一个可能更直接的解决方案是使用用户脚本管理器,并以可以通过键盘组合激活的用户脚本的形式定义书签。 See, for example this user script , reproduced here for completeness:参见,例如这个用户脚本,为了完整起见,复制在这里:

// Add the following as a user-script (via an extension like https://github.com/violentmonkey/violentmonkey) in order to copy the
// current webpage and selected text to the clipboard in a format suitable for pasting into an org-mode document.
// To execute the action, you need to press Alt-C on a webpage, though this can be modified by changing the keycode
// used in the onkeyup function.

// ==UserScript==
// @name Copy Org-mode Link
// @namespace Violentmonkey Scripts
// @match *://*/*
// @grant clipboardWrite
// ==/UserScript==

function main() {
    function copyTextToClipboard(text) { var textArea = document.createElement("textarea"); textArea.style.position = 'fixed'; textArea.style.top = 0; textArea.style.left = 0; textArea.style.width = '2em'; textArea.style.height = '2em'; textArea.style.padding = 0; textArea.style.border = 'none'; textArea.style.outline = 'none'; textArea.style.boxShadow = 'none'; textArea.style.background = 'transparent'; textArea.value = text; document.body.appendChild(textArea); textArea.select(); try { var successful = document.execCommand('copy'); var msg = successful ? 'successful' : 'unsuccessful'; console.log('Copying text command was ' + msg); } catch (err) { console.log('Oops, unable to copy'); } document.body.removeChild(textArea); }; var url = encodeURIComponent(location.href); url = url.replace(/%253A/g, ':').replace(/%252F/g, '/'); var title = document.title; title = title.replace(/\[/g, '{'); title = title.replace(/\]/g, '}'); var sel_text = window.getSelection(); copyTextToClipboard('[['+url+']['+title+']]'+'\n\n'+sel_text);
}

// listen for Alt-C key-combination, and then execute
document.onkeyup=function(e){
    var e = e || window.event; // for IE to cover IEs window object
    if(e.altKey && e.which == 67) {
         main();
         return false;
    }
}

An answer that's a bit unusual: open a blank page from which the user will copy the text:一个有点不寻常的答案:打开一个空白页面,用户将从中复制文本:

<a href="javascript:window.open('data:text/html, <html contenteditable>sup<script>document.execCommand(\'selectAll\')</script></html>')">
  Copy the text “sup”
</a>

Just replace sup by the text you want the user to copy.只需将sup替换为您希望用户复制的文本即可。

JS Bin example JS Bin 示例

Here's how I solved it, using the technique @zzzzBov mentioned in his answer , to import zeroclipboard into the page via a bookmarklet.这是我解决它的方法,使用@zzzzBov 在他的回答中提到的技术,通过书签将zeroclipboard导入页面。

When the bookmarket runs, a hand cursor appears on hovering over anywhere on the body.当书市运行时,将出现一个手形光标,悬停在身体​​的任何地方。 Clicking will copy (for example) the document's title to the clipboard.单击将复制(例如)文档的标题到剪贴板。

(Links to zeroclipboard resources have been replaced with placeholders, and multi-line comments have been used since Chrome appears to be removing all line-breaks from bookmarklets (or something)) (指向 zeroclipboard 资源的链接已被占位符替换,并且由于 Chrome 似乎正在从书签(或其他东西)中删除所有换行符,因此使用了多行注释)

javascript:

var s = document.createElement('script');
s.setAttribute('src', 'http://example.com/ZeroClipboard.js');

s.onload = s.onreadystatechange = 
  function()
  { 
     ZeroClipboard.setMoviePath( 'http://example.com/ZeroClipboard.swf');
     var clip = new ZeroClipboard.Client();   

     /* glue to the body: sample only, in reality  we should
        probably create a new visible element and glue to that. */
     clip.glue(document.body);   

     clip.setHandCursor( true );

     /* copy to clipboard on mouse-up */
     clip.addEventListener('onMouseUp', 
      function (client) 
      {      
         /* example */
         var toCopy = document.title;        
         clip.setText(toCopy);    

         alert(toCopy + ' copied.');
         clip.hide();
      });  
   };

document.body.appendChild(s);

A couple disclaimers:一些免责声明:

  1. I'm not trying to spam you我不是要向你发送垃圾邮件
  2. I gain nothing if you choose to use this如果您选择使用它,我将一无所获

I made a bookmarklet generator a while back to make it easier for me to create bookmarklets.不久前,我制作了一个书签生成器,以便我更轻松地创建书签。

It's jQuery enabled, but that doesn't mean you have to use jQuery.它启用了 jQuery,但这并不意味着您必须使用 jQuery。

You can check out the source to see how to import another script/library into a page via a bookmarklet.您可以查看源代码以了解如何通过书签将另一个脚本/库导入页面。

In particular, the lines that import jQuery:特别是,导入 jQuery 的行:

if (!window.zbooks)
  {
    //if zbooks hasn't been set, initialize it

    //s used for the Script element
    var s = document.createElement('script');
    //r used for the Ready state
    var r = false;
    //set the script to the latest version of jQuery
    s.setAttribute('src', 'http://code.jquery.com/jquery-latest.min.js');
    //set the load/readystate events
    s.onload = s.onreadystatechange = function()
    {
/**
 * LOAD/READYSTATE LOGIC
 * execute if the script hasn't been ready yet and:
 * - the ready state isn't set
 * - the ready state is complete
 *   - note: readyState == 'loaded' executes before the script gets called so
 *     we skip this event because it wouldn't have loaded the init event yet.
 */
      if ( !r && (!this.readyState || this.readyState == 'complete' ) )
      {
        //set the ready flag to true to keep the event from initializing again
        r = true;
        //prevent jQuery conflicts by placing jQuery in the zbooks object
        window.zbooks = {'jQuery':jQuery.noConflict()};
        //make a new zbook
        window.zbooks[n] = new zbooks(c);
      }
    };
    //append the jQuery script to the body
    b.appendChild(s);
  }

I hope that helps.我希望这有帮助。

A solution for both HTTP and HTTPS contexts一种用于HTTP和HTTPS上下文溶液

The Clipboard API solution by @Joachim Lous was on the right track for me. @Joachim Lous 的剪贴板 API解决方案对我来说是正确的。 However, this did not work on localhost, which used http not https.但是,这在使用 http 而不是 https 的 localhost 上不起作用。 To get around this, I used a "copyToClipboard" function (adapted from this SO answer ) which acts as an all-in-one wrapper function that takes into account a http context by using a clever "out of viewport hidden text area" trick.为了解决这个问题,我使用了一个“copyToClipboard”函数(改编自这个 SO answer ),它作为一个多合一的包装函数,通过使用一个聪明的“视口外隐藏文本区域”技巧来考虑 http 上下文.

Readable version:可读版本:

javascript:

function copyToClipboard(textToCopy) {
    // navigator clipboard api needs a secure context (https)
    if (navigator.clipboard && window.isSecureContext) {
        // navigator clipboard api method
        return navigator.clipboard.writeText(textToCopy);
    } else {
        // use the 'out of viewport hidden text area' trick
        let textArea = document.createElement("textarea");
        textArea.value = textToCopy;
        // make the textarea out of viewport
        textArea.style.position = "fixed";
        textArea.style.left = "-999999px";
        textArea.style.top = "-999999px";
        document.body.appendChild(textArea);
        textArea.focus();
        textArea.select();
        return new Promise((res, rej) => {
            // here the magic happens
            document.execCommand('copy') ? res() : rej();
            textArea.remove();
        });
    }
};
var element = document.querySelector(".myClass");
var text = element.textContent || element.value;
copyToClipboard(text);

Simply replace ".myClass" with your selector.只需用您的选择器替换“.myClass”。

Minified version for bookmarklet:书签的缩小版:

javascript:void function(){var a=document.querySelector(".myClass"),b=a.textContent||a.value;(function(a){if(navigator.clipboard&&window.isSecureContext)return navigator.clipboard.writeText(a);else{let b=document.createElement("textarea");return b.value=a,b.style.position="fixed",b.style.left="-999999px",b.style.top="-999999px",document.body.appendChild(b),b.focus(),b.select(),new Promise((a,c)=>{document.execCommand("copy")?a():c(),b.remove()})}})(b)}();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM