What Web Can Do Today?

Can I rely on the Web Platform features to build my app?

An overview of the device integration HTML5 APIs

Clipboard (Copy & Paste)

The Clipboard API gives Web applications a way to react on cut, copy and paste operations performed by the user as well as read from or write to the system clipboard directly on behalf of user.

There are two flavors of Clipboard API available - the older, synchronous, and the newer, asynchronous. The newer API is limited to HTTPS and require explicit user permission for pasting operation – it is not available in Safari as of early 2020, though. The older API did not address privacy concerns properly and thus pasting is no longer functional in most browsers.

API glimpse

Older, synchronous API

document.addEventListener('cut/copy/paste', listener)
An event fired when the user invoked the particular clipboard operation (either cut, copy or paste).
event.clipboardData.setData('text/plain', data)
Sets the data that is to be written to the clipboard by the cut or copy operations in the specified format.
event.clipboardData.getData('text/plain')
Returns the data that has been read from the clipboard by the paste operation in the specified format.
document.execCommand('cut/copy/paste')
Programatically invokes the specified clipboard operation (either cut, copy or paste) on the data or element currently having a focus.

Newer, asynchronous API

navigator.clipboard.writeText(text)
Writes the text to the clipboard. Returns a Promise resolved when the operation has succeeded.
navigator.clipboard.readText()
Returns a Promise resolved with the text read from the clipboard.
navigator.clipboard.write(new ClipboardItem(data))
Writes the generic ClipboardItem data to the clipboard, allowing it to handle objects of different types, i.e. images. Returns a Promise resolved when the operation has succeeded.
const clipboardItem = await navigator.clipboard.read()
Returns a Promise resolved with the array of ClipboardItems read from the clipboard.
const blob = await clipboardItem.getType(type)
Returns a Promise resolved with the data of requested type read from the clipboard.

Live Demo

Use the forms below for programmatic clipboard access or invoke standard copy/cut/paste operations with your keyboard.


Cut/Paste Example

Copy Example

Email me at matt@example.co.uk

Demo based on Google Chrome examples.

  • var logTarget = document.getElementById('logTarget');
    
    function useAsyncApi() {
      return document.querySelector('input[value=async]').checked;
    }
    
    function log(event) {
      var timeBadge = new Date().toTimeString().split(' ')[0];
      var newInfo = document.createElement('p');
      newInfo.innerHTML = '<span class="badge">' + timeBadge + '</span> ' + event + '</b>.';
      logTarget.appendChild(newInfo);
    }
    
    function performCopyEmail() {
      var selection = window.getSelection();
      var emailLink = document.querySelector('.js-emaillink');
    
      if (useAsyncApi()) {
        navigator.clipboard.writeText(emailLink.textContent)
          .then(() => log('Async writeText successful, "' + emailLink.textContent + '" written'))
          .catch(err => log('Async writeText failed with error: "' + err + '"'));
      } else {
        selection.removeAllRanges();
        var range = document.createRange();
        range.selectNode(emailLink);
        selection.addRange(range);
      
        try {
          var successful = document.execCommand('copy');
          var msg = successful ? 'successful' : 'unsuccessful';
          log('Copy email command was ' + msg);
        } catch (err) {
          log('execCommand Error', err);
        }
        
        selection.removeAllRanges();
      }
    }
    
    function performCutTextarea() {
      var cutTextarea = document.querySelector('.js-cuttextarea');
    
      if (useAsyncApi()) {
        navigator.clipboard.writeText(cutTextarea.textContent)
          .then(() => {
            log('Async writeText successful, "' + cutTextarea.textContent + '" written');
            cutTextarea.textContent = '';
          })
          .catch(err => log('Async writeText failed with error: "' + err + '"'));
      } else {
        var hasSelection = document.queryCommandEnabled('cut');
        cutTextarea.select();
      
        try {
          var successful = document.execCommand('cut');
          var msg = successful ? 'successful' : 'unsuccessful';
          log('Cutting text command was ' + msg);
        } catch (err) {
          log('execCommand Error', err);
        }
      }
    }
    
    function performPaste() {
      var pasteTextarea = document.querySelector('.js-cuttextarea');
      
      if (useAsyncApi()) {
        navigator.clipboard.readText()
          .then((text) => {
            pasteTextarea.textContent = text;
            log('Async readText successful, "' + text + '" written');
          })
          .catch((err) => log('Async readText failed with error: "' + err + '"'));
      } else {
        pasteTextarea.focus();
        try {
          var successful = document.execCommand('paste');
          var msg = successful ? 'successful' : 'unsuccessful';
          log('Pasting text command was ' + msg);
        } catch (err) {
          log('execCommand Error', err);
        }
      }
    }
    
    // Get the buttons
    var cutTextareaBtn = document.querySelector('.js-textareacutbtn');
    var copyEmailBtn = document.querySelector('.js-emailcopybtn');
    var pasteTextareaBtn = document.querySelector('.js-textareapastebtn');
    
    // Add click event listeners
    copyEmailBtn.addEventListener('click', performCopyEmail);
    cutTextareaBtn.addEventListener('click', performCutTextarea);
    pasteTextareaBtn.addEventListener('click', performPaste);
    
    function logUserOperation(event) {
      log('User performed <b>' + event.type + '</b> operation. Payload is: <b>' + event.clipboardData.getData('text/plain') + '</b>');
    }
    
    document.addEventListener('cut', logUserOperation);
    document.addEventListener('copy', logUserOperation);
    document.addEventListener('paste', logUserOperation);
  • <p class="heading">Use the forms below for programmatic clipboard access or invoke standard copy/cut/paste operations with your keyboard.</p>
    <section>
      <label><input type="radio" name="api" value="sync"> Use older, synchronous API</label><br/>
      <label><input type="radio" name="api" value="async" checked> Use newer, asynchronous API</label>
    </section>
    <section>
      <h2>Cut/Paste Example</h2>
      <p>
        <textarea class="js-cuttextarea">Hello! Cut me programatically or maybe try pasting here.</textarea>
      </p>
    
      <p>
        <button class="js-textareacutbtn">Cut text programatically</button>
        <button class="js-textareapastebtn">Paste text programatically</button>
      </p>
    </section>
    
    <section>
      <h2>Copy Example</h2>
      <p>Email me at <a class="js-emaillink" href="mailto:matt@example.co.uk">matt@example.co.uk</a></p>
      <p>
        <button class="js-emailcopybtn">Copy Email Address programatically</button>
      </p>
    </section>
    
    <p id="logTarget"></p>
    
    <p><small>Demo based on <a href="https://googlechrome.github.io/samples/cut-and-copy/index.html" target="_blank" rel="noopener">Google Chrome examples</a>.</small></p>

Resources

Get in touch