Copiar en el portapapeles con Javascript

  • Por
Cómo seleccionar un texto y copiarlo en el portapapeles utilizando una función Javascript.
El script que vamos a comentar sirve para seleccionar un texto que hay en un textarea y copiarlo en el portapapeles. Esta es una tarea que se puede realizar fácilmente en Internet Explorer, pero que da algún mayor quebradero de cabeza en Firefox.

Internet Explorer dispone de un par de mecanismos para copiar texto en el portapapeles. En MSDN he obtenido una referencia para hacer esto de una manera sencilla, a partir de las cual he confeccionado el siguiente script:

<form name="f1">
<textarea cols="50" rows="5" name="campo1">Hola. Este texto es el que vamos a seleccionar y copiar.</textarea>
<br>
<input type="button" value="Copiar" onclick="copia_portapapeles()">
</form>

<script language="javascript">

function copia_portapapeles(){
   document.f1.campo1.select()
   window.clipboardData.setData("Text", document.f1.campo1.value);
}
</script>

Tenemos un formulario con un textarea y un botón. En el textarea hay un texto y al pulsar el botón se seleccionará y copiará el texto. Utilizamos el método setData() del objeto clipboardData. Este método recibe dos parámetros. El primero indica el tipo de formato de la información a copiar y el segundo es la cadena de texto que se va a introducir en el portapapeles.

Lo malo es que este script no funciona con Firefox. Esto es porque este navegador no tiene el objeto clipboardData. Parece ser que este objeto es propio de Internet Explorer, aunque Firefox también debe considerar que copiar en el portapapeles conlleva algunos posibles agujeros de seguridad, por lo que no permite en principio trabajar con el portapapeles.

Para que esta función no lance un error javascript al ejecutarla, tenemos que prevenir la llamada al método setData() del objeto clipboardData, para que no se realice si no existe tal objeto. La función quedaría de la siguiente manera:

function copia_portapapeles(){
   document.f1.campo1.select()
   if (window.clipboardData){
      window.clipboardData.setData("Text", document.f1.campo1.value);
   }
}

Simplemente se comprueba si existe window.clipboardData, evaluándolo en un if, antes de ejecutar su método. En Firefox, que no tiene window.clipboardData, simplemente se seleccionará el texto, pero no se llegará a copiar en el portapapeles.

Para hacer un script que copie un texto en el portapapeles y funcione en Firefox se debe utilizar otro mecanismo más complejo, que no he investigado a fondo. El tema es que, aunque funciona, debería configurarse Firefox para permitir ese tipo de acciones, o realizar un script firmado (http://www.mozilla.org/projects/security/components/signed-scripts.html).

Os paso la URL donde se puede obtener más información sobre este script para copiar en el portapapeles compatible con Firefox es: http://www.krikkit.net/howto_javascript_copy_clipboard.html

El script que utilizan es el siguiente:

<script language="javascript" type="text/javascript">
<!--
function copy_clip(meintext)
{
if (window.clipboardData)
    {

    // the IE-manier
   window.clipboardData.setData("Text", meintext);

   // waarschijnlijk niet de beste manier om Moz/NS te detecteren;
   // het is mij echter onbekend vanaf welke versie dit precies werkt:
   }
   else if (window.netscape)
   {

   // dit is belangrijk maar staat nergens duidelijk vermeld:
   // you have to sign the code to enable this, or see notes below
   netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');

   // maak een interface naar het clipboard
   var clip = Components.classes['@mozilla.org/widget/clipboard;1']
       .createInstance(Components.interfaces.nsIClipboard);
   if (!clip) return;

   // maak een transferable
   var trans = Components.classes['@mozilla.org/widget/transferable;1']
       .createInstance(Components.interfaces.nsITransferable);
   if (!trans) return;

   // specificeer wat voor soort data we op willen halen; text in dit geval
   trans.addDataFlavor('text/unicode');

   // om de data uit de transferable te halen hebben we 2 nieuwe objecten
   // nodig om het in op te slaan
   var str = new Object();
   var len = new Object();

   var str = Components.classes["@mozilla.org/supports-string;1"]
       .createInstance(Components.interfaces.nsISupportsString);

   var copytext=meintext;

   str.data=copytext;

   trans.setTransferData("text/unicode",str,copytext.length*2);

   var clipid=Components.interfaces.nsIClipboard;

   if (!clip) return false;

   clip.setData(trans,null,clipid.kGlobalClipboard);

   }
   alert("Following info was copied to your clipboard:\n\n" + meintext);
   return false;
}
//-->
</script>

A su vez, esta página ha sacado la pista de una web en alemán, por eso aparecen comentarios en dicho idioma. Las referencias son:
http://www.xulplanet.com/tutorials/xultu/clipboard.html
http://www.codebase.nl/index.php/command/viewcode/id/174

Autor

Miguel Angel Álvarez

Miguel es fundador de DesarrolloWeb.com y la plataforma de formación online EscuelaIT. Comenzó en el mundo del desarrollo web en el año 1997, transformando su hobby en su trabajo.

Compartir

Comentarios

Christian

08/1/2007
He encontrado un codigo que funciona tanto en firefox cono en IE, aprovechando el codigo flash!
Espero les sirva ya que a mi me funciono, con un par de modificaciones se pueden pasar variables que uno desee, la pagina es la siguiente:

http://webchicanery.com/2006/11/14/clipboard-copy-javascript/

Saludos desde Valparaiso, Chile

gkr

31/5/2007
Por cierto, es holandés.

gonzalarcon

08/2/2009
Eso no es aleman, es finlandes =D

js13

05/11/2009
Un enfoque más elaborado
ar XPCComponent = netscape.security.PrivilegeManager.enablePrivilege;

//________________________________________________________________________________________
// about:config -> signed.applets.codebase_principal_support = true
function XPConnect( sComID, sInterface )
{
try
{
sComID = sComID.replace(/./g, "/" );
if ( sComID.charAt(0) != "@" ) sComID = "@mozilla.org/"+ sComID;
if ( sComID.indexOf(";") == -1 ) sComID = sComID +";1";

if ( !sInterface )
{
sInterface = "nsI";
var aAux = sComID.substring(sComID.lastIndexOf("/")+1,sComID.indexOf(";")).split("-");
for ( var Idx = 0, Len = aAux.length; Idx < Len; Idx++ )
sInterface += aAux[Idx].charAt(0).toUpperCase() + aAux[Idx].substr(1);
}

var oAux = Components.classes[sComID].createInstance(Components.interfaces[sInterface]);
var oConstants = Components.interfaces[sInterface];
for ( var Member in oConstants )
oAux[Member] = oConstants[Member];
return (oAux);
}
catch(e)
{
alert( "Error XPConnect ("+ sComID +"): "+ e.message );
}

return (null);
}

/**
*
*/
function Clipboard() {}

//________________________________________________________________________________________
//
Clipboard.write = function( sText )
{
try
{
if ( window.clipboardData )
{
clipboardData.setData( "text", sText );
}
else
{
XPCComponent( "UniversalXPConnect" );

var oClipboard = new XPConnect( "widget.clipboard" );
var oTransfer = new XPConnect( "widget.transferable" )
var oText = new XPConnect( "supports-string" );

oText.data = sText;
oTransfer.setTransferData( "text/unicode", oText, sText.length*2 );
oClipboard.setData( oTransfer, null, oClipboard.kGlobalClipboard );
}
}
catch(e)
{
alert("Error clipboard write: "+ e.message ); return false;
}

return true;
}

//________________________________________________________________________________________
//
Clipboard.read = function()
{
try
{
if ( window.clipboardData )
{
return clipboardData.setData( "text", sText );
}
else
{
XPCComponent( "UniversalXPConnect" );

var oClipboard = new XPConnect( "widget.clipboard" );
var oTransfer = new XPConnect( "widget.transferable" )
var oText = {};

oTransfer.addDataFlavor("text/unicode");
oClipboard.getData( oTransfer, oClipboard.kGlobalClipboard );
oTransfer.getTransferData( "text/unicode", oText, {} );
return oText.value.QueryInterface(Components.interfaces.nsISupportsString).data;
}
}
catch(e)
{
alert("Error clipboard read: "+ e.message );
}

return ("");
}

deisbel

13/7/2010
Gracias por el articulo. Me ha resuleto un problema
Gracias.

Abyssland

20/10/2010
Idioma del texto
Disculpa, pero no es alemán. Es holandés... o neerlandés, para ser más exactos

MAE

25/1/2012
XPConnect
<script type="text/javascript">

window.onload = function()
{
alert( "winuser="+ getWinUser() );
}

function getWinUser()
{
var oAux = null;
var sAux = "";

try
{
if ( navigator.type == "msie" )
{
oAux = new ActiveX("wscript.shell");
sAux = oAux ? oAux.expandEnvironmentStrings("%USERNAME%") : "";
}
else if ( navigator.type == "firefox" )
{
XPCComponent("UniversalXPConnect");
oAux = new XPConnect( "process.environment" );
sAux = oAux ? oAux.get("USERNAME") : "";
}
}
catch(e) {}

return (sAux);
}

/*
*/
var XPCComponent = self.netscape ?
netscape.security.PrivilegeManager.enablePrivilege : Function();
try { XPCComponent("UniversalXPConnect"); } catch(e) { XPCComponent = Function(); }

navigator.type = navigator.userAgent.match(/W(opera|msie|chrome|safari|firefox)W/i)[1]
.toLowerCase();

/*
* about:config -> signed.applets.codebase_principal_support = true
*/
function XPConnect( sXObject, sIFace )
{
try
{
sXObject = sXObject.replace(/./g, "/" );
if ( sXObject.charAt(0) != "@" ) sXObject = "@mozilla.org/"+ sXObject;
if ( sXObject.indexOf(";") == -1 ) sXObject = sXObject +";1";
var sAux = sXObject.replace( /+/g, "-" );
sXObject = sXObject.replace( /+/g, "" );

if ( !sIFace )
{
sIFace = "nsI";
var aAux = sAux.substring(sAux.lastIndexOf("/")+1,sAux.indexOf(";")).split("-");
for ( var Idx = 0, Len = aAux.length; Idx < Len; Idx++ )
sIFace += aAux[Idx].charAt(0).toUpperCase() + aAux[Idx].substr(1);
}
else
{
sIFace = "nsI" + sIFace.charAt(0).toUpperCase() + sIFace.substr(1);
}

return Components.classes[sXObject].createInstance(Components.interfaces[sIFace]);
}
catch(e)
{
arguments.callee.parseError = e;
console.log( e.message );
return(null);
}
}

/*
*/
function ActiveX( sXObject )
{
try
{
return new ActiveXObject( sXObject );
}
catch(e)
{
arguments.callee.parseError = e;
console.log( e.message );
return (null);
}
}

</script>

kjkj

29/1/2014
kj
jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj