Vraag Hoe kopieer ik naar het klembord in JavaScript?


Wat is de beste manier om tekst naar het klembord te kopiëren? (Multi-browser)

Ik heb geprobeerd:

function copyToClipboard(text) {
    if (window.clipboardData) { // Internet Explorer
        window.clipboardData.setData("Text", text);
    } else {  
        unsafeWindow.netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");  
        const clipboardHelper = Components.classes["@mozilla.org/widget/clipboardhelper;1"].getService(Components.interfaces.nsIClipboardHelper);  
        clipboardHelper.copyString(text);
    }
}

maar in Internet Explorer geeft het een syntaxisfout. In Firefox staat het unsafeWindow is not defined.

Een leuke truc zonder flits: Hoe heeft Trello toegang tot het klembord van de gebruiker?


2663
2017-12-30 13:09


oorsprong


antwoorden:


Overzicht

Er zijn 3 primaire browser-API's om naar het klembord te kopiëren:

  1. Async Clipboard API  [navigator.clipboard.writeText]
    • Tekstgericht gedeelte beschikbaar in Chrome 66 (maart 2018)
    • Toegang is asynchroon en gebruikt JavaScript-beloften, kan zo worden geschreven dat beveiligingsgebruikersmeldingen (indien weergegeven) de JavaScript-pagina niet onderbreken.
    • Tekst kan rechtstreeks vanuit een variabele naar het klembord worden gekopieerd.
    • Alleen ondersteund op pagina's die via HTTPS worden weergegeven.
    • In Chrome 66 kunnen pagina's in actieve tabbladen naar het klembord schrijven zonder een machtigingsprompt.
  2. document.execCommand('copy')
    • De meeste browsers ondersteunen dit vanaf ~ april 2015 (zie Browserondersteuning hieronder).
    • Toegang is synchroon, d.w.z. stopt JavaScript op de pagina totdat het voltooid is, inclusief weergeven en gebruikersinteractie met beveiligingsaanwijzingen.
    • Tekst wordt gelezen van de DOM en op het klembord geplaatst.
    • Tijdens het testen ~ april 2015 werd alleen Internet Explorer genoteerd als het tonen van permissies prompts tijdens het schrijven naar het klembord.
  3. De kopieergebeurtenis overschrijven
    • Zie Klembord API-documentatie op De kopieergebeurtenis overschrijven.
    • Hiermee kunt u wijzigen wat op het klembord wordt weergegeven van elke kopieergebeurtenis, andere indelingen van gegevens dan alleen onbewerkte tekst opnemen.
    • Hier niet genoemd omdat het niet direct de vraag beantwoordt.

Algemene ontwikkelingstips

Verwacht niet dat klembordgerelateerde opdrachten werken terwijl je code test in de console. Over het algemeen moet de pagina actief zijn (Async Clipboard API) of vereist gebruikersinteractie (bijvoorbeeld een klik van een gebruiker) om toe te staan ​​(document.execCommand('copy')) om toegang te krijgen tot het klembord, zie hieronder voor meer informatie.

Async + fallback

Vanwege het niveau van browserondersteuning voor de nieuwe Async Clipboard API wilt u waarschijnlijk terugvallen op de document.execCommand('copy') methode om een ​​goede browser-dekking te krijgen.

Hier is een eenvoudig voorbeeld:

function fallbackCopyTextToClipboard(text) {
  var textArea = document.createElement("textarea");
  textArea.value = text;
  document.body.appendChild(textArea);
  textArea.focus();
  textArea.select();

  try {
    var successful = document.execCommand('copy');
    var msg = successful ? 'successful' : 'unsuccessful';
    console.log('Fallback: Copying text command was ' + msg);
  } catch (err) {
    console.error('Fallback: Oops, unable to copy', err);
  }

  document.body.removeChild(textArea);
}
function copyTextToClipboard(text) {
  if (!navigator.clipboard) {
    fallbackCopyTextToClipboard(text);
    return;
  }
  navigator.clipboard.writeText(text).then(function() {
    console.log('Async: Copying to clipboard was successful!');
  }, function(err) {
    console.error('Async: Could not copy text: ', err);
  });
}

var copyBobBtn = document.querySelector('.js-copy-bob-btn'),
  copyJaneBtn = document.querySelector('.js-copy-jane-btn');

copyBobBtn.addEventListener('click', function(event) {
  copyTextToClipboard('Bob');
});


copyJaneBtn.addEventListener('click', function(event) {
  copyTextToClipboard('Jane');
});
<div style="display:inline-block; vertical-align:top;">
  <button class="js-copy-bob-btn">Set clipboard to BOB</button><br /><br />
  <button class="js-copy-jane-btn">Set clipboard to JANE</button>
</div>
<div style="display:inline-block;">
  <textarea class="js-test-textarea" cols="35" rows="4">Try pasting into here to see what you have on your clipboard:
  
  </textarea>
</div>

Merk op dat dit fragment niet goed werkt in de ingesloten preview van StackOverflow, u kunt het hier proberen: https://codepen.io/DeanMarkTaylor/pen/RMRaJX?editors=1011

Async Clipboard API

Merk op dat er een mogelijkheid is om "toestemming te vragen" en te testen op toegang tot het klembord via de permissies-API in Chrome 66.

var text = "Example text to appear on clipboard";
navigator.clipboard.writeText(text).then(function() {
  console.log('Async: Copying to clipboard was successful!');
}, function(err) {
  console.error('Async: Could not copy text: ', err);
});

document.execCommand ( 'copy')

De rest van dit bericht gaat in op de nuances en details van de document.execCommand('copy') API.

Browserondersteuning

JavaScript document.execCommand('copy') ondersteuning is gegroeid, zie de onderstaande links voor browserupdates:

Eenvoudig voorbeeld

var copyTextareaBtn = document.querySelector('.js-textareacopybtn');

copyTextareaBtn.addEventListener('click', function(event) {
  var copyTextarea = document.querySelector('.js-copytextarea');
  copyTextarea.focus();
  copyTextarea.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');
  }
});
<p>
  <button class="js-textareacopybtn" style="vertical-align:top;">Copy Textarea</button>
  <textarea class="js-copytextarea">Hello I'm some text</textarea>
</p>

Complex voorbeeld: kopiëren naar klembord zonder invoer weer te geven

Het bovenstaande eenvoudige voorbeeld werkt prima als er een is textarea of input element zichtbaar op het scherm.

In sommige gevallen wilt u mogelijk tekst kopiëren naar het klembord zonder een input / textarea element. Dit is een voorbeeld van een manier om dit te omzeilen (eigenlijk element invoegen, kopiëren naar klembord, element verwijderen):

Getest met Google Chrome 44, Firefox 42.0a1 en IE 11.0.8600.17814.

function copyTextToClipboard(text) {
  var textArea = document.createElement("textarea");

  //
  // *** This styling is an extra step which is likely not required. ***
  //
  // Why is it here? To ensure:
  // 1. the element is able to have focus and selection.
  // 2. if element was to flash render it has minimal visual impact.
  // 3. less flakyness with selection and copying which **might** occur if
  //    the textarea element is not visible.
  //
  // The likelihood is the element won't even render, not even a flash,
  // so some of these are just precautions. However in IE the element
  // is visible whilst the popup box asking the user for permission for
  // the web page to copy to the clipboard.
  //

  // Place in top-left corner of screen regardless of scroll position.
  textArea.style.position = 'fixed';
  textArea.style.top = 0;
  textArea.style.left = 0;

  // Ensure it has a small width and height. Setting to 1px / 1em
  // doesn't work as this gives a negative w/h on some browsers.
  textArea.style.width = '2em';
  textArea.style.height = '2em';

  // We don't need padding, reducing the size if it does flash render.
  textArea.style.padding = 0;

  // Clean up any borders.
  textArea.style.border = 'none';
  textArea.style.outline = 'none';
  textArea.style.boxShadow = 'none';

  // Avoid flash of white box if rendered for any reason.
  textArea.style.background = 'transparent';


  textArea.value = text;

  document.body.appendChild(textArea);
  textArea.focus();
  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 copyBobBtn = document.querySelector('.js-copy-bob-btn'),
  copyJaneBtn = document.querySelector('.js-copy-jane-btn');

copyBobBtn.addEventListener('click', function(event) {
  copyTextToClipboard('Bob');
});


copyJaneBtn.addEventListener('click', function(event) {
  copyTextToClipboard('Jane');
});
<div style="display:inline-block; vertical-align:top;">
  <button class="js-copy-bob-btn">Set clipboard to BOB</button><br /><br />
  <button class="js-copy-jane-btn">Set clipboard to JANE</button>
</div>
<div style="display:inline-block;">
  <textarea class="js-test-textarea" cols="35" rows="4">Try pasting into here to see what you have on your clipboard:
  
  </textarea>
</div>

Extra notities

Werkt alleen als de gebruiker een actie onderneemt

Alle document.execCommand('copy') oproepen moeten plaatsvinden als een direct resultaat van een gebruikersactie, b.v. klik op gebeurtenishandler. Dit is een maatregel om geknoei met het klembord van gebruikers te voorkomen wanneer ze het niet verwachten.

Zie de Google Developers post hier voor meer informatie.

Klembord-API

Merk op dat de volledige specificatie van de Clipboard API-draft hier te vinden is: https://w3c.github.io/clipboard-apis/

Wordt het ondersteund?

  • document.queryCommandSupported('copy') zou terug moeten keren true als het commando "wordt ondersteund door de browser".
  • en document.queryCommandEnabled('copy') terugkeer true als het document.execCommand('copy') zal slagen als hij nu wordt gebeld. Controleren of de opdracht is aangeroepen vanuit een door een gebruiker gestarte thread en aan andere vereisten is voldaan.

Echter, als een voorbeeld van problemen met browsercompatibiliteit, keerde Google Chrome van ~ april tot ~ oktober 2015 alleen terug true van document.queryCommandSupported('copy') als het commando werd aangeroepen vanuit een door de gebruiker geïnitieerde thread.

Let op compatibiliteitsdetails hieronder.

Browser Compatibiliteit Detail

Terwijl een eenvoudige oproep aan document.execCommand('copy') ingepakt in een try/catch blok dat wordt aangeroepen als gevolg van een klik van een gebruiker, krijgt u de meeste compatibiliteitsgebruik, het volgende heeft een aantal voorwaarden:

Elke oproep naar document.execCommand, document.queryCommandSupported of document.queryCommandEnabled moet worden ingepakt in een try/catch blok.

Verschillende browserimplementaties en browserversies werpen verschillende soorten uitzonderingen wanneer ze worden gebeld in plaats van terug te keren false.

Verschillende browserimplementaties zijn nog steeds in beweging en de Klembord-API zit nog steeds in de ontwerpfase, dus vergeet niet om te testen.


1581
2018-06-12 18:56



Automatisch kopiëren naar het klembord kan gevaarlijk zijn, daarom maken de meeste browsers (behalve IE) het erg moeilijk. Persoonlijk gebruik ik de volgende eenvoudige truc:

function copyToClipboard(text) {
  window.prompt("Copy to clipboard: Ctrl+C, Enter", text);
}

De gebruiker krijgt het promptvenster te zien, waar de te kopiëren tekst al is geselecteerd. Nu is het genoeg om op te drukken Ctrl+C en invoeren (om de doos te sluiten) - en voila!

Nu is de kopieerbewerking op het klembord SAFE, omdat de gebruiker dit handmatig doet (maar op een vrij eenvoudige manier). Werkt natuurlijk in alle browsers.

<button id="demo" onclick="copyToClipboard(document.getElementById('demo').innerHTML)">This is what I want to copy</button>

<script>
  function copyToClipboard(text) {
    window.prompt("Copy to clipboard: Ctrl+C, Enter", text);
  }
</script>


1195
2018-05-19 08:06



De volgende aanpak werkt in Chrome, Firefox, Internet Explorer en Edge en in recente versies van Safari (ondersteuning voor kopiëren is toegevoegd in versie 10 die oktober 2016 is uitgebracht).

  • Maak een tekstgebied en stel de inhoud ervan in op de tekst die u naar het klembord wilt kopiëren.
  • Voeg het tekstgebied toe aan de DOM.
  • Selecteer de tekst in het tekstgebied.
  • Bel document.execCommand ("kopiëren")
  • Verwijder het tekstgebied van de dom.

Opmerking: u ziet het textarea niet, omdat het wordt toegevoegd en verwijderd binnen dezelfde synchrone aanroep van Javascript-code.

Sommige dingen om op te letten als u dit zelf uitvoert:

  • Om veiligheidsredenen kan dit alleen worden aangeroepen vanuit een gebeurtenishandler, zoals klikken (net als bij het openen van vensters).
  • IE toont een dialoogvenster voor toestemming wanneer het klembord voor de eerste keer wordt bijgewerkt.
  • IE en Edge scrolt wanneer het tekstgebied is gefocust.
  • execCommand () kan in sommige gevallen gooien.
  • Nieuwe regels en tabbladen kunnen worden ingeslikt, tenzij u een tekstgebied gebruikt. (De meeste artikelen lijken aan te bevelen om een ​​div te gebruiken)
  • Het tekstveld zal zichtbaar zijn terwijl het IE-dialoogvenster wordt getoond, je moet het verbergen of het IE-specifieke clipboardData-api gebruiken.
  • In IE-systeem kunnen beheerders de klembord-API uitschakelen.

De onderstaande functie moet alle onderstaande problemen zo schoon mogelijk behandelen. Laat een opmerking achter als u problemen ondervindt of suggesties heeft om deze te verbeteren.

// Copies a string to the clipboard. Must be called from within an 
// event handler such as click. May return false if it failed, but
// this is not always possible. Browser support for Chrome 43+, 
// Firefox 42+, Safari 10+, Edge and IE 10+.
// IE: The clipboard feature may be disabled by an administrator. By
// default a prompt is shown the first time the clipboard is 
// used (per session).
function copyToClipboard(text) {
    if (window.clipboardData && window.clipboardData.setData) {
        // IE specific code path to prevent textarea being shown while dialog is visible.
        return clipboardData.setData("Text", text); 

    } else if (document.queryCommandSupported && document.queryCommandSupported("copy")) {
        var textarea = document.createElement("textarea");
        textarea.textContent = text;
        textarea.style.position = "fixed";  // Prevent scrolling to bottom of page in MS Edge.
        document.body.appendChild(textarea);
        textarea.select();
        try {
            return document.execCommand("copy");  // Security exception may be thrown by some browsers.
        } catch (ex) {
            console.warn("Copy to clipboard failed.", ex);
            return false;
        } finally {
            document.body.removeChild(textarea);
        }
    }
}

https://jsfiddle.net/fx6a6n6x/


194
2017-11-26 00:03



Als je een heel eenvoudige oplossing wilt (die minder dan 5 minuten nodig heeft om te integreren) en er meteen goed uitziet, dan is Clippy een goed alternatief voor sommige van de complexere oplossingen.

Clippy

Het werd geschreven door een mede-oprichter van Github. Voorbeeld Flash embed-code hieronder:

<object 
   classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"
   width="110"
   height="14"
   id="clippy">
  <param name="movie" value="/flash/clippy.swf"/>
  <param name="allowScriptAccess" value="always"/>
  <param name="quality" value="high"/>
  <param name="scale" value="noscale"/>
  <param NAME="FlashVars" value="text=#{text}"/>
  <param name="bgcolor" value="#{bgcolor}"/>
  <embed 
     src="/flash/clippy.swf"
     width="110"
     height="14"
     name="clippy"
     quality="high"
     allowScriptAccess="always"
     type="application/x-shockwave-flash"
     pluginspage="http://www.macromedia.com/go/getflashplayer"
     FlashVars="text=#{text}"
     bgcolor="#{bgcolor}"/>
</object>

Vergeet niet om te vervangen #{text} met de tekst die u wilt kopiëren, en #{bgcolor} met een kleur.


93
2017-10-17 14:40



Het lezen en wijzigen van het klembord van een webpagina verhoogt de beveiliging en privacy. In Internet Explorer is het echter mogelijk om dit te doen. ik vond dit voorbeeldfragment:

    <script type="text/javascript">
        function select_all(obj) {
            var text_val=eval(obj);
            text_val.focus();
            text_val.select();
            r = text_val.createTextRange();
            if (!r.execCommand) return; // feature detection
            r.execCommand('copy');
        }
    </script>
    <input value="http://www.sajithmr.com"
     onclick="select_all(this)" name="url" type="text" />


77
2017-12-30 13:33



Ik heb onlangs een geschreven technische blogpost over dit probleem (ik werk bij Lucidchart en we hebben onlangs een revisie op ons klembord gedaan).

Het kopiëren van platte tekst naar het klembord is relatief eenvoudig, ervan uitgaande dat u dit wilt doen tijdens een systeemkopieerdement (gebruiker drukt hierop) CtrlC of gebruikt het browsermenu).

var isIe = (navigator.userAgent.toLowerCase().indexOf("msie") != -1 
           || navigator.userAgent.toLowerCase().indexOf("trident") != -1);

document.addEventListener('copy', function(e) {
    var textToPutOnClipboard = "This is some text";
    if (isIe) {
        window.clipboardData.setData('Text', textToPutOnClipboard);    
    } else {
        e.clipboardData.setData('text/plain', textToPutOnClipboard);
    }
    e.preventDefault();
});

Het plaatsen van tekst op het klembord tijdens een systeemkopieerdatum is veel moeilijker. Het lijkt erop dat sommige van deze andere antwoorden verwijzen naar manieren om dit via Flash te doen, wat de enige manier is om dit te doen (voor zover ik begrijp).

Verder zijn er enkele opties per browser.

Dit is het meest eenvoudig in IE, waar je op elk moment toegang hebt tot het clipboardData-object vanuit JavaScript via:

window.clipboardData

(Wanneer u probeert dit te doen buiten een systeem knip-, kopieer- of plak-gebeurtenis, zal IE de gebruiker echter vragen om toestemming van het webtoepassingklembord.)

In Chrome kunt u een Chrome-extensie maken die u dit geeft klembord toestemmingen (dit is wat we doen voor Lucidchart). Voor gebruikers met uw extensie geïnstalleerd, hoeft u alleen maar de systeemgebeurtenis zelf te starten:

document.execCommand('copy');

Het lijkt erop dat Firefox heeft sommige opties waarmee gebruikers toestemmingen aan bepaalde sites verlenen om toegang te krijgen tot het klembord, maar ik heb geen van deze persoonlijk geprobeerd.


65
2017-12-03 20:31



clipboard.js is een klein, niet-flashig hulpprogramma dat het kopiëren van tekst of html-gegevens naar het klembord mogelijk maakt. Het is heel gemakkelijk te gebruiken, neem gewoon de .js op en gebruik zoiets als dit:

<button id='markup-copy'>Copy Button</button>

<script>
document.getElementById('markup-copy').addEventListener('click', function() {
  clipboard.copy({
    'text/plain': 'Markup text. Paste me into a rich text editor.',
    'text/html': '<i>here</i> is some <b>rich text</b>'
  }).then(
    function(){console.log('success'); },
    function(err){console.log('failure', err);
  });

});
</script>

clipboard.js is ook ingeschakeld GitHub


44
2017-08-11 15:33



ZeroClipboard is de beste cross-browseroplossing die ik heb gevonden:

<div id="copy" data-clipboard-text="Copy Me!">Click to copy</div>    
<script src="ZeroClipboard.js"></script>
<script>
  var clip = new ZeroClipboard( document.getElementById('copy') );
</script>

Als je niet-flash-ondersteuning voor iOS nodig hebt, voeg je gewoon een fall-back toe:

clip.on( 'noflash', function ( client, args ) {
    $("#copy").click(function(){            
        var txt = $(this).attr('data-clipboard-text');
        prompt ("Copy link, then click OK.", txt);
    });
});  

http://zeroclipboard.org/

https://github.com/zeroclipboard/ZeroClipboard


35
2017-11-21 20:41



Hier is mijn mening over die ene ..

function copy(text) {
    var input = document.createElement('input');
    input.setAttribute('value', text);
    document.body.appendChild(input);
    input.select();
    var result = document.execCommand('copy');
    document.body.removeChild(input)
    return result;
 }

29
2017-09-14 09:20



Van een van de projecten waaraan ik heb gewerkt, een plug-in voor jQuery-kopiëren naar het klembord die gebruikmaakt van de Nul klembord bibliotheek.

Het is gemakkelijker te gebruiken dan de native Zero Clipboard-plug-in als je een zware jQuery-gebruiker bent.


25
2018-05-03 22:17