Clipboard preview
by Comandeer
HTML
<div contenteditable id="preview"></div>
<dl id="details"></dl>
CSS
#preview {
border: 5px dashed red;
padding: 10px;
min-height: 2em;
}
#preview:empty::after {
content: 'Paste or drop inside me!';
}
#preview:focus-within::after {
content: '';
}
dt {
font-weight: bold;
font-size: bigger;
}
dd {
padding-bottom: 1em;
margin-bottom: 1em;
border-bottom: 2px solid black;
}
JavaScript
const preview = document.querySelector( '#preview' );
const details = document.querySelector( '#details' );
preview.addEventListener( 'paste', handleDataTransferEvent );
preview.addEventListener( 'drop', handleDataTransferEvent );
function handleDataTransferEvent( evt ) {
const data = evt.clipboardData || evt.dataTransfer;
if ( evt.type === 'drop' ) {
evt.preventDefault();
}
details.innerHTML = '';
[ ...data.items ].forEach( ( item ) => {
const type = item.type;
convertToHTML( item, ( html ) => {
details.insertAdjacentHTML( 'beforeend', `<dt>${ type }</dt><dd>${ html }</dd>` );
} );
} );
[ ...data.files ].forEach( ( file, i ) => {
details.insertAdjacentHTML( 'beforeend', `<dt>File #${ i }</dt><dd>${ file.name } (${ file.size }B)<br>${ handleFile( file ) }</dd>` );
} )
}
function convertToHTML( item, callback ) {
if ( item.type.startsWith( 'text/' ) ) {
return item.getAsString( callback );
}
const file = item.getAsFile( ( file ) => {
const image = handleFile( file );
callback( image );
} );
}
function handleFile( file ) {
const url = URL.createObjectURL( file );
if ( !file.type.startsWith( 'image') ) {
return url;
}
return `<img src="${ url }" alt="">`;
}