usando - ¿Cómo copio al portapapeles en JavaScript?




script copiar al portapapeles (20)

Visión general

Hay 3 API principales del navegador para copiar al portapapeles:

  1. Async Clipboard API [navigator.clipboard.writeText]
    • Parte centrada en el texto disponible en Chrome 66 (marzo de 2018)
    • El acceso es asíncrono y utiliza promesas de JavaScript , que se pueden escribir para que las indicaciones de seguridad del usuario (si se muestran) no interrumpan el JavaScript en la página.
    • El texto se puede copiar al portapapeles directamente desde una variable.
    • Sólo se admite en páginas servidas a través de HTTPS.
    • En Chrome 66, las páginas en pestañas activas pueden escribir en el portapapeles sin una solicitud de permisos.
  2. document.execCommand('copy')
    • La mayoría de los navegadores lo admiten a partir de abril de 2015 (consulte la sección Soporte del navegador a continuación).
    • El acceso es sincrónico, es decir, detiene JavaScript en la página hasta que se complete, incluida la visualización y la interacción del usuario con cualquier mensaje de seguridad.
    • El texto se lee desde el DOM y se coloca en el portapapeles.
    • Durante las pruebas ~ abril de 2015, solo se observó que Internet Explorer mostraba solicitudes de permisos al escribir en el portapapeles.
  3. Anulando el evento de copia
    • Consulte la documentación de la API del Portapapeles sobre Anular el evento de copia .
    • Le permite modificar lo que aparece en el portapapeles de cualquier evento de copia, puede incluir otros formatos de datos que no sean texto sin formato.
    • No se cubre aquí ya que no responde directamente a la pregunta.

Notas de desarrollo general.

No espere que los comandos relacionados con el portapapeles funcionen mientras prueba el código en la consola. En general, se requiere que la página esté activa (Async Clipboard API) o que requiera la interacción del usuario (por ejemplo, un clic del usuario) para permitir que ( document.execCommand('copy') ) acceda al portapapeles, consulte a continuación para obtener más detalles.

Async + Fallback

Debido al nivel de compatibilidad del navegador para la nueva API de Async Clipboard, es probable que desee recurrir al método document.execCommand('copy') para obtener una buena cobertura del navegador.

Aquí hay un ejemplo simple:

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>

Tenga en cuenta que este fragmento de código no funciona bien en la vista previa integrada de StackOverflow. Puede probarlo aquí: https://codepen.io/DeanMarkTaylor/pen/RMRaJX?editors=1011

API async portapapeles

Tenga en cuenta que existe la posibilidad de "solicitar permiso" y probar el acceso al portapapeles a través de la API de permisos en 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 ('copiar')

El resto de esta publicación incluye los matices y detalles de la API document.execCommand('copy') .

Soporte del navegador

El soporte de JavaScript document.execCommand('copy') ha crecido, vea los enlaces a continuación para obtener actualizaciones del navegador:

Ejemplo simple

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>

Ejemplo complejo: copiar al portapapeles sin mostrar la entrada

El ejemplo simple anterior funciona muy bien si hay un área de textarea o elemento de input visible en la pantalla.

En algunos casos, es posible que desee copiar texto en el portapapeles sin mostrar un elemento input / textarea . Este es un ejemplo de una forma de solucionar esto (básicamente, insertar elemento, copiar en el portapapeles, eliminar elemento):

Probado con Google Chrome 44, Firefox 42.0a1 e 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>

Notas adicionales

Solo funciona si el usuario realiza una acción.

Todas document.execCommand('copy') llamadas document.execCommand('copy') deben tener lugar como resultado directo de una acción del usuario, por ejemplo, hacer clic en el controlador de eventos. Esta es una medida para evitar entrometerse con el portapapeles de los usuarios cuando no lo esperan.

Consulte la publicación de desarrolladores de Google aquí para obtener más información.

API del portapapeles

Tenga en cuenta que la especificación de borrador de la API del Portapapeles se puede encontrar aquí: https://w3c.github.io/clipboard-apis/

¿Es compatible?

  • document.queryCommandSupported('copy') debe devolver true si el comando "es compatible con el navegador".
  • y document.queryCommandEnabled('copy') devuelve true si el document.execCommand('copy') tendrá éxito si se llama ahora. Comprobación para garantizar que se haya llamado al comando desde un subproceso iniciado por el usuario y que se cumplan otros requisitos.

Sin embargo, como ejemplo de problemas de compatibilidad del navegador, Google Chrome de ~ abril a ~ octubre de 2015 solo devolvió true desde document.queryCommandSupported('copy') si se invocó el comando desde un hilo iniciado por el usuario.

Tenga en cuenta los detalles de compatibilidad a continuación.

Detalle de compatibilidad del navegador

Si bien una simple llamada a document.execCommand('copy') envuelta en un bloque try / catch llamado como resultado de un clic del usuario le proporcionará el mayor uso de compatibilidad, tiene algunas condiciones:

Cualquier llamada a document.execCommand , document.queryCommandSupported o document.queryCommandEnabled debe incluirse en un bloque try / catch .

Las diferentes implementaciones de navegador y las versiones de navegador generan diferentes tipos de excepciones cuando se invocan en lugar de devolver false .

Las diferentes implementaciones de los navegadores aún están en movimiento y la https://w3c.github.io/clipboard-apis/ del https://w3c.github.io/clipboard-apis/ aún está en borrador, así que recuerde hacer sus pruebas.

¿Cuál es la mejor manera de copiar texto al portapapeles? (multi-navegador)

Yo he tratado:

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

pero en Internet Explorer da un error de sintaxis. En Firefox, dice que unsafeWindow is not defined .

Un buen truco sin flash: ¿Cómo accede Trello al portapapeles del usuario?


Aquí está mi opinión sobre esa ...

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

El siguiente enfoque funciona en Chrome, Firefox, Internet Explorer y Edge, y en las versiones recientes de Safari (el soporte de Copias se agregó en la versión 10 que se lanzó en octubre de 2016).

  • Cree un área de texto y configure su contenido al texto que desea copiar en el portapapeles.
  • Agregue el área de texto al DOM.
  • Selecciona el texto en el área de texto.
  • Llamar document.execCommand ("copia")
  • Retire el área de texto del dom.

Nota: no verá el área de texto, ya que se agrega y elimina dentro de la misma invocación sincrónica del código Javascript.

Algunas cosas a tener en cuenta si lo está implementando usted mismo:

  • Por razones de seguridad, esto solo se puede realizar desde un controlador de eventos, como hacer clic (al igual que con la apertura de ventanas).
  • IE mostrará un diálogo de permisos la primera vez que se actualice el portapapeles.
  • IE y Edge se desplazarán cuando el área de texto esté enfocada.
  • execCommand () puede lanzar en algunos casos.
  • Las líneas nuevas y las pestañas se pueden tragar a menos que uses un área de texto. (La mayoría de los artículos parecen recomendar el uso de un div)
  • El área de texto será visible mientras se muestra el cuadro de diálogo de IE, o bien debe ocultarlo o usar la api específica para el portapapeles de IE.
  • En IE, los administradores del sistema pueden deshabilitar la API del portapapeles.

La siguiente función debe manejar todos los problemas siguientes de la manera más limpia posible. Por favor, deje un comentario si encuentra algún problema o tiene alguna sugerencia para mejorarlo.

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


He encontrado la siguiente solución:

En clave, el controlador crea una etiqueta "pre". Configuramos el contenido para copiar en esta etiqueta, luego hacemos una selección en esta etiqueta y devolvemos verdadero en el controlador. Esto llama al controlador estándar de Chrome y copia el texto seleccionado.

Y si lo necesita, puede configurar el tiempo de espera para la función de restauración de la selección anterior. Mi implementación en Mootools:

   function EnybyClipboard() {
     this.saveSelection = false;
     this.callback = false;
     this.pastedText = false;

     this.restoreSelection = function() {
       if (this.saveSelection) {
         window.getSelection().removeAllRanges();
         for (var i = 0; i < this.saveSelection.length; i++) {
           window.getSelection().addRange(this.saveSelection[i]);
         }
         this.saveSelection = false;
       }
     };

     this.copyText = function(text) {
       var div = $('special_copy');
       if (!div) {
         div = new Element('pre', {
           'id': 'special_copy',
           'style': 'opacity: 0;position: absolute;top: -10000px;right: 0;'
         });
         div.injectInside(document.body);
       }
       div.set('text', text);
       if (document.createRange) {
         var rng = document.createRange();
         rng.selectNodeContents(div);
         this.saveSelection = [];
         var selection = window.getSelection();
         for (var i = 0; i < selection.rangeCount; i++) {
           this.saveSelection[i] = selection.getRangeAt(i);
         }
         window.getSelection().removeAllRanges();
         window.getSelection().addRange(rng);
         setTimeout(this.restoreSelection.bind(this), 100);
       } else return alert('Copy not work. :(');
     };

     this.getPastedText = function() {
       if (!this.pastedText) alert('Nothing to paste. :(');
       return this.pastedText;
     };

     this.pasteText = function(callback) {
       var div = $('special_paste');
       if (!div) {
         div = new Element('textarea', {
           'id': 'special_paste',
           'style': 'opacity: 0;position: absolute;top: -10000px;right: 0;'
         });
         div.injectInside(document.body);
         div.addEvent('keyup', function() {
           if (this.callback) {
             this.pastedText = $('special_paste').get('value');
             this.callback.call(null, this.pastedText);
             this.callback = false;
             this.pastedText = false;
             setTimeout(this.restoreSelection.bind(this), 100);
           }
         }.bind(this));
       }
       div.set('value', '');
       if (document.createRange) {
         var rng = document.createRange();
         rng.selectNodeContents(div);
         this.saveSelection = [];
         var selection = window.getSelection();
         for (var i = 0; i < selection.rangeCount; i++) {
           this.saveSelection[i] = selection.getRangeAt(i);
         }
         window.getSelection().removeAllRanges();
         window.getSelection().addRange(rng);
         div.focus();
         this.callback = callback;
       } else return alert('Fail to paste. :(');
     };
   }

Uso:

enyby_clip = new EnybyClipboard(); //init 

enyby_clip.copyText('some_text'); // place this in CTRL+C handler and return true;

enyby_clip.pasteText(function callback(pasted_text) {
        alert(pasted_text);
}); // place this in CTRL+V handler and return true;

Al pegar crea textarea y funciona de la misma manera.

PS puede ser que esta solución se pueda utilizar para crear una solución de navegador completo sin flash. Sus obras en FF y Chrome.


Leer y modificar el portapapeles desde una página web plantea problemas de seguridad y privacidad. Sin embargo, en Internet Explorer, es posible hacerlo. Encontré este fragmento de ejemplo :

    <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" />


Recientemente escribí una publicación técnica en el blog sobre este mismo problema (trabajo en Lucidchart y recientemente hicimos una revisión en nuestro portapapeles).

Copiar texto sin formato en el portapapeles es relativamente simple, suponiendo que desee hacerlo durante un evento de copia del sistema (el usuario presiona Ctrl C o usa el menú del navegador).

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();
});

Poner texto en el portapapeles no durante un evento de copia del sistema es mucho más difícil. Parece que algunas de estas otras respuestas hacen referencia a formas de hacerlo a través de Flash, que es la única forma de hacerlo en varios navegadores (según tengo entendido).

Aparte de eso, hay algunas opciones en una base de navegador por navegador.

Este es el más simple en IE, donde puede acceder al objeto clipboardData en cualquier momento desde JavaScript a través de:

window.clipboardData

(Sin embargo, cuando intenta hacer esto fuera de un evento de corte, copia o pegado del sistema, IE solicitará al usuario que otorgue el permiso del portapapeles de la aplicación web).

En Chrome, puede crear una extensión de Chrome que le dará permisos de portapapeles (esto es lo que hacemos para Lucidchart). Luego, para los usuarios con su extensión instalada, solo tendrá que disparar el evento del sistema usted mismo:

document.execCommand('copy');

Parece que Firefox tiene algunas opciones que permiten a los usuarios otorgar permisos a ciertos sitios para acceder al portapapeles, pero no he probado ninguno de estos personalmente.


ZeroClipboard es la mejor solución de navegador cruzado que he encontrado:

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

Si necesita soporte no flash para iOS, simplemente agregue una alternativa:

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


clipboard.js es una pequeña utilidad no flash que permite copiar texto o datos html al portapapeles. Es muy fácil de usar, solo incluye el .js y usa algo como esto:

<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 también está en GitHub



Esta es una expansión de la respuesta de @ Chase, con la ventaja de que funcionará para los elementos de IMAGEN y TABLA, no solo DIV en IE9.

if (document.createRange) {
    // IE9 and modern browsers
    var r = document.createRange();
    r.setStartBefore(to_copy);
    r.setEndAfter(to_copy);
    r.selectNode(to_copy);
    var sel = window.getSelection();
    sel.addRange(r);
    document.execCommand('Copy');  // does nothing on FF
} else {
    // IE 8 and earlier.  This stuff won't work on IE9.
    // (unless forced into a backward compatibility mode,
    // or selecting plain divs, not img or table). 
    var r = document.body.createTextRange();
    r.moveToElementText(to_copy);
    r.select()
    r.execCommand('Copy');
}

He encontrado la siguiente solución:

Tengo el texto en una entrada oculta. Como setSelectionRangeno funciona en entradas ocultas, cambié temporalmente el tipo a texto, copié el texto y luego lo oculté nuevamente. Si desea copiar el texto de un elemento, puede pasarlo a la función y guardar su contenido en la variable de destino.

    jQuery('#copy').on('click', function () {
        copyToClipboard();
    });

    function copyToClipboard() {
        var target = jQuery('#hidden_text');

        // make it visible, so can be focused
        target.attr('type', 'text');
        target.focus();
        // select all the text
        target[0].setSelectionRange(0, target.val().length);

        // copy the selection
        var succeed;
        try {
            succeed = document.execCommand("copy");
        } catch (e) {
            succeed = false;
        }

        // hide input again
        target.attr('type', 'hidden');

        return succeed;
    }

He reunido lo que creo que es el mejor.

  • Utiliza cssText para evitar excepciones en IE en lugar de estilo directamente.
  • Restaura la selección si hubiera una.
  • Se configura solo para que el teclado no aparezca en dispositivos móviles.
  • Tiene una solución para iOS para que realmente funcione, ya que normalmente bloquea execCommand.

Aquí está:

const copyToClipboard = (function initClipboardText() {
  const textarea = document.createElement('textarea');

  // Move it off screen.
  textarea.style.cssText = 'position: absolute; left: -99999em';

  // Set to readonly to prevent mobile devices opening a keyboard when
  // text is .select()'ed.
  textarea.setAttribute('readonly', true);

  document.body.appendChild(textarea);

  return function setClipboardText(text) {
    textarea.value = text;

    // Check if there is any content selected previously.
    const selected = document.getSelection().rangeCount > 0 ?
      document.getSelection().getRangeAt(0) : false;

    // iOS Safari blocks programmtic execCommand copying normally, without this hack.
    // https://.com/questions/34045777/copy-to-clipboard-using-javascript-in-ios
    if (navigator.userAgent.match(/ipad|ipod|iphone/i)) {
      const editable = textarea.contentEditable;
      textarea.contentEditable = true;
      const range = document.createRange();
      range.selectNodeContents(textarea);
      const sel = window.getSelection();
      sel.removeAllRanges();
      sel.addRange(range);
      textarea.setSelectionRange(0, 999999);
      textarea.contentEditable = editable;
    } else {
      textarea.select();
    }

    try {
      const result = document.execCommand('copy');

      // Restore previous selection.
      if (selected) {
        document.getSelection().removeAllRanges();
        document.getSelection().addRange(selected);
      }

      return result;
    } catch (err) {
      return false;
    }
  };
})();


  <!DOCTYPE html>

  <style>
    #t {
      width: 1px
      height: 1px
      border: none
    }
    #t:focus {
      outline: none
    }
  </style>

  <script>
    function copy(text) {
      var t = document.getElementById('t')
      t.innerHTML = text
      t.select()
      try {
        var successful = document.execCommand('copy')
        var msg = successful ? 'successfully' : 'unsuccessfully'
        console.log('text coppied ' + msg)
      } catch (err) {
        console.log('Unable to copy text')
      }
      t.innerHTML = ''
    }
  </script>

  <textarea id=t></textarea>

  <button onclick="copy('hello world')">
    Click me
  </button>


Desde hace poco, Chrome 42+y Firefox 41+ahora admite el comando document.execCommand ('copy') . Así que creé un par de funciones para la capacidad de copia del navegador en el portapapeles utilizando una combinación de la respuesta anterior de Tim Down y la respuesta del desarrollador de Google :

function selectElementContents(el) {
    // Copy textarea, pre, div, etc.
    if (document.body.createTextRange) {
        // IE 
        var textRange = document.body.createTextRange();
        textRange.moveToElementText(el);
        textRange.select();
        textRange.execCommand("Copy");
    } else if (window.getSelection && document.createRange) {
        // non-IE
        var range = document.createRange();
        range.selectNodeContents(el);
        var sel = window.getSelection();
        sel.removeAllRanges();
        sel.addRange(range);
        try {
            var successful = document.execCommand('copy');
            var msg = successful ? 'successful' : 'unsuccessful';
            console.log('Copy command was ' + msg);
        } catch (err) {
            console.log('Oops, unable to copy');
        }
    }
} // end function selectElementContents(el) 

function make_copy_button(el) {
    var copy_btn = document.createElement('input');
    copy_btn.type = "button";
    el.parentNode.insertBefore(copy_btn, el.nextSibling);
    copy_btn.onclick = function() {
        selectElementContents(el);
    };

    if (document.queryCommandSupported("copy") || parseInt(navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./)[2]) >= 42) {
        // Copy works with IE 4+, Chrome 42+, Firefox 41+, Opera 29+
        copy_btn.value = "Copy to Clipboard";
    } else {
        // Select only for Safari and older Chrome, Firefox and Opera
        copy_btn.value = "Select All (then press CTRL+C to Copy)";
    }
}
/* Note: document.queryCommandSupported("copy") should return "true" on browsers that support copy
	but there was a bug in Chrome versions 42 to 47 that makes it return "false".  So in those
	versions of Chrome feature detection does not work!
	See https://code.google.com/p/chromium/issues/detail?id=476508
*/

make_copy_button(document.getElementById("markup"));
<pre id="markup">
  Text that can be copied or selected with cross browser support.
</pre>


Lo uso con mucho éxito ( sin jquery o cualquier otro framework).

function copyToClp(txt){
    txt = document.createTextNode(txt);
    document.body.appendChild(txt);
    if (document.body.createTextRange) {
        var d = document.body.createTextRange();
        d.moveToElementText(txt);
        d.select();
        document.execCommand('copy');
    } else {
        var d = document.createRange();
        d.selectNodeContents(txt);
        window.getSelection().removeAllRanges();
        window.getSelection().addRange(d);
        document.execCommand('copy');
        window.getSelection().removeAllRanges();
    }
    txt.remove();
} 

Advertencia

Las pestañas se convierten en espacios (al menos en cromo).


Mi error. Esto solo funciona en IE.

Aquí hay otra forma de copiar texto:

<p>
    <a onclick="window.clipboardData.setData('text', document.getElementById('Test').innerText);">Copy</a>
</p>

Muchas respuestas ya pero me gusta agregar una (jQuery). Funciona como un encanto en cualquier navegador, también en dispositivos móviles (es decir, avisos sobre seguridad, pero cuando lo acepta, simplemente funciona bien).

function appCopyToClipBoard( sText )
{
 var oText = false,
     bResult = false;
 try
 {
  oText = document.createElement("textarea");
  $(oText).addClass('clipboardCopier').val(sText).insertAfter('body').focus();
  oText.select();
  document.execCommand("Copy");
  bResult = true;
 } catch(e) {}

 $(oText).remove();
 return bResult;
}

En su código:

if( !appCopyToClipBoard( 'Hai there! This is copied to the clipboard.' ))
 { alert('Sorry, copy to clipboard failed.'); }

Parece que he leído mal la pregunta, pero para referencia, puede extraer un rango del DOM (no para el portapapeles; compatible con todos los navegadores modernos) y combinarlo con los eventos oncopy y onpaste y on beforepaste para obtener el comportamiento del portapapeles. Aquí está el código para lograr esto:

function clipBoard(sCommand) {
  var oRange=contentDocument.createRange();
  oRange.setStart(startNode, startOffset);
  oRange.setEnd(endNode, endOffset);
/* This is where the actual selection happens.
in the above, startNode and endNode are dom nodes defining the beginning 
and end of the "selection" respectively. startOffset and endOffset are 
constants that are defined as follows:

END_TO_END: 2
END_TO_START: 3
NODE_AFTER: 1
NODE_BEFORE: 0
NODE_BEFORE_AND_AFTER: 2
NODE_INSIDE: 3
START_TO_END: 1
START_TO_START: 0

and would be used like oRange.START_TO_END */
      switch(sCommand) {
    case "cut":
          this.oFragment=oRange.extractContents();
      oRange.collapse();
      break;
    case "copy":
      this.oFragment=oRange.cloneContents();
      break;
    case "paste":
      oRange.deleteContents();
      var cloneFragment=this.oFragment.cloneNode(true)
      oRange.insertNode(cloneFragment);
      oRange.collapse();
      break;
  }
}

Tuve el mismo problema al crear una edición de cuadrícula personalizada desde (algo como Excel) y compatibilidad con Excel. Tuve que apoyar la selección de varias celdas, copiar y pegar.

Solución: cree un área de texto donde insertará datos para que el usuario los copie (para mí cuando el usuario esté seleccionando celdas), céntrese (por ejemplo, cuando el usuario presione Ctrl) y seleccione todo el texto.

Entonces, cuando el usuario pulsa Ctrl+ Cobtiene las celdas copiadas, él selecciona. Después de la prueba, solo redimensioné el área de texturas a 1 píxel (no probé si funcionará en la pantalla: ninguna). Funciona bien en todos los navegadores y es transparente para el usuario.

Pegado: podría hacer lo mismo de esta manera (difiere en su objetivo): concentrarse en los eventos de área de texto y de pegado mediante el uso de la pasta (en mi proyecto utilizo las áreas de texto en las celdas para editar)

No puedo pegar un ejemplo (proyecto comercial), pero tienes la idea.





copy-paste