Rozwiązanie nr 1 (tylko zwykły tekst i wymaga przeglądarki Firefox 22+)
Działa dla IE6 +, FF 22+, Chrome, Safari, Edge (testowany tylko w IE9 +, ale powinien działać dla niższych wersji)
Jeśli potrzebujesz pomocy przy wklejaniu HTML lub Firefox <= 22, zobacz Rozwiązanie nr 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/
Zauważ, że w tym rozwiązaniu użyto parametru „Tekst” dla getData
funkcji, co jest niestandardowe. Działa jednak we wszystkich przeglądarkach w momencie pisania.
Rozwiązanie nr 2 (HTML i działa w przeglądarce Firefox <= 22)
Testowane w 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/
Wyjaśnienie
onpaste
Wydarzenie div
ma handlePaste
funkcję dołączony do niej i podał jeden argument: event
obiekt dla zdarzenia wklejania. Szczególnie interesuje nas clipboardData
właściwość tego wydarzenia, która umożliwia dostęp do schowka w innych przeglądarkach. W IE odpowiednikiem jest window.clipboardData
, choć ma nieco inny interfejs API.
Zobacz sekcję zasobów poniżej.
handlepaste
Funkcja:
Ta funkcja ma dwie gałęzie.
Pierwsze sprawdzenie istnienia event.clipboardData
i sprawdzenie, czy jego types
właściwość zawiera „text / html” ( types
może to być albo DOMStringList
sprawdzany za pomocą contains
metody, albo ciąg sprawdzany za pomocąindexOf
metody). Jeśli wszystkie te warunki są spełnione, postępujemy jak w rozwiązaniu nr 1, z wyjątkiem „text / html” zamiast „text / plain”. Obecnie działa to w Chrome i Firefox 22+.
Jeśli ta metoda nie jest obsługiwana (wszystkie inne przeglądarki), to my
- Zapisz zawartość elementu w
DocumentFragment
- Opróżnij element
- Wywołaj
waitForPastedData
funkcję
waitforpastedata
Funkcja:
Ta funkcja najpierw sonduje wklejone dane (raz na 20 ms), co jest konieczne, ponieważ nie pojawia się od razu. Gdy pojawią się dane:
- Zapisuje innerHTML edytowalnego div (który jest teraz wklejonym danymi) do zmiennej
- Przywraca zawartość zapisaną w DocumentFragment
- Wywołuje funkcję „processPaste” z pobranymi danymi
processpaste
Funkcja:
Wykonuje dowolne czynności z wklejonymi danymi. W takim przypadku po prostu ostrzegamy dane, możesz zrobić, co chcesz. Prawdopodobnie będziesz chciał uruchomić wklejone dane w procesie dezynfekcji danych.
Zapisywanie i przywracanie pozycji kursora
W prawdziwej sytuacji prawdopodobnie zechcesz wcześniej zapisać wybór i przywrócić go później ( Ustaw pozycję kursora na contentEditable <div> ). Następnie można wstawić wklejone dane w miejscu, w którym znajdował się kursor, gdy użytkownik zainicjował akcję wklejania.
Zasoby:
Dziękujemy Timowi Downowi za zasugerowanie użycia DocumentFragment i dziękuję za złapanie błędu w Firefoksie z powodu użycia DOMStringList zamiast ciągu dla clipboardData.types