Soluzione n. 1 (solo testo normale e richiede Firefox 22+)
Funziona con IE6 +, FF 22+, Chrome, Safari, Edge (testato solo su IE9 +, ma dovrebbe funzionare per le versioni precedenti)
Se hai bisogno di supporto per incollare HTML o Firefox <= 22, vedi Soluzione n. 2.
HTML
<div id='editableDiv' contenteditable='true'>Paste</div>
JavaScript
function handlePaste (e) {
var clipboardData, pastedData;
// Stop data actually being pasted into div
e.stopPropagation();
e.preventDefault();
// Get pasted data via clipboard API
clipboardData = e.clipboardData || window.clipboardData;
pastedData = clipboardData.getData('Text');
// Do whatever with pasteddata
alert(pastedData);
}
document.getElementById('editableDiv').addEventListener('paste', handlePaste);
JSFiddle: https://jsfiddle.net/swL8ftLs/12/
Questa soluzione utilizza il parametro 'Testo' per la getData
funzione, che non è standard. Tuttavia, funziona in tutti i browser al momento della scrittura.
Soluzione n. 2 (HTML e funziona per Firefox <= 22)
Testato in IE6 +, FF 3.5+, Chrome, Safari, Edge
HTML
<div id='div' contenteditable='true'>Paste</div>
JavaScript
var editableDiv = document.getElementById('editableDiv');
function handlepaste (e) {
var types, pastedData, savedContent;
// Browsers that support the 'text/html' type in the Clipboard API (Chrome, Firefox 22+)
if (e && e.clipboardData && e.clipboardData.types && e.clipboardData.getData) {
// Check for 'text/html' in types list. See abligh's answer below for deatils on
// why the DOMStringList bit is needed. We cannot fall back to 'text/plain' as
// Safari/Edge don't advertise HTML data even if it is available
types = e.clipboardData.types;
if (((types instanceof DOMStringList) && types.contains("text/html")) || (types.indexOf && types.indexOf('text/html') !== -1)) {
// Extract data and pass it to callback
pastedData = e.clipboardData.getData('text/html');
processPaste(editableDiv, pastedData);
// Stop the data from actually being pasted
e.stopPropagation();
e.preventDefault();
return false;
}
}
// Everything else: Move existing element contents to a DocumentFragment for safekeeping
savedContent = document.createDocumentFragment();
while(editableDiv.childNodes.length > 0) {
savedContent.appendChild(editableDiv.childNodes[0]);
}
// Then wait for browser to paste content into it and cleanup
waitForPastedData(editableDiv, savedContent);
return true;
}
function waitForPastedData (elem, savedContent) {
// If data has been processes by browser, process it
if (elem.childNodes && elem.childNodes.length > 0) {
// Retrieve pasted content via innerHTML
// (Alternatively loop through elem.childNodes or elem.getElementsByTagName here)
var pastedData = elem.innerHTML;
// Restore saved content
elem.innerHTML = "";
elem.appendChild(savedContent);
// Call callback
processPaste(elem, pastedData);
}
// Else wait 20ms and try again
else {
setTimeout(function () {
waitForPastedData(elem, savedContent)
}, 20);
}
}
function processPaste (elem, pastedData) {
// Do whatever with gathered data;
alert(pastedData);
elem.focus();
}
// Modern browsers. Note: 3rd argument is required for Firefox <= 6
if (editableDiv.addEventListener) {
editableDiv.addEventListener('paste', handlepaste, false);
}
// IE <= 8
else {
editableDiv.attachEvent('onpaste', handlepaste);
}
JSFiddle: https://jsfiddle.net/nicoburns/wrqmuabo/23/
Spiegazione
L' onpaste
evento di div
ha la handlePaste
funzione associata e ha passato un singolo argomento: l' event
oggetto per l'evento paste. Di particolare interesse per noi è la clipboardData
proprietà di questo evento che consente l'accesso agli Appunti nei browser non ie. In IE l'equivalente è window.clipboardData
, sebbene abbia un'API leggermente diversa.
Vedi la sezione risorse di seguito.
La handlepaste
funzione:
Questa funzione ha due rami.
Il primo controlla l'esistenza event.clipboardData
e controlla se la sua types
proprietà contiene 'text / html' ( types
può essere o una DOMStringList
che viene controllata usando il contains
metodo, o una stringa che viene controllata usando il indexOf
metodo). Se tutte queste condizioni sono soddisfatte, procediamo come nella soluzione n. 1, tranne con "text / html" anziché "text / plain". Questo attualmente funziona in Chrome e Firefox 22+.
Se questo metodo non è supportato (tutti gli altri browser), allora noi
- Salvare il contenuto dell'elemento in a
DocumentFragment
- Svuota l'elemento
- Chiama la
waitForPastedData
funzione
La waitforpastedata
funzione:
Questa funzione esegue prima il polling dei dati incollati (una volta ogni 20 ms), il che è necessario perché non appare immediatamente. Quando i dati sono apparsi:
- Salva il HTML interno del div modificabile (che ora è i dati incollati) in una variabile
- Ripristina il contenuto salvato in DocumentFragment
- Chiama la funzione 'processPaste' con i dati recuperati
La processpaste
funzione:
Fa cose arbitrarie con i dati incollati. In questo caso avvisiamo solo i dati, puoi fare quello che vuoi. Probabilmente vorrai eseguire i dati incollati attraverso una sorta di processo di sanificazione dei dati.
Salvataggio e ripristino della posizione del cursore
In una vera e propria seduta probabilmente vorrai salvare la selezione prima e ripristinarla in seguito ( Imposta la posizione del cursore su contentEditable <div> ). È quindi possibile inserire i dati incollati nella posizione in cui si trovava il cursore quando l'utente ha avviato l'azione incolla.
risorse:
Grazie a Tim Down per aver suggerito l'uso di DocumentFragment e per aver scoperto un errore in Firefox a causa dell'uso di DOMStringList invece di una stringa per appuntiData.types