Frontend Weeky logo

Frontend News

THE CLIPBOARD API
CRASHCOURSE

Frontend News #2

David East - Author David East — August 1st, 2018

The hotkey everyone knows

Not everyone prefers to order their computer around with hotkeys. There's a large group of users and programmers alike who rely on graphical menus and buttons. However, if there's one hotkey combination everyone knows, it's Cmd+C, Cmd+V. And yes, of course Ctrl+C, Ctrl+V on Windows. But what actually happens when you copy?

The Clipboard is a data buffer

Every major operating system comes with a "Clipboard". It's a data buffer for short-term storage, sometimes referred to as the "paste-buffer". The new copy or cut command replaces the previous value in the buffer. Nearly all programs have access to this buffer. Otherwise we'd be annoyed when nothing happens when we hit Cmd+V.

Automatically copying complex text can be good UX

Often on sites we need to present a user with a special code or text. This text is usually long and downright looks like gibberish. The user will likely copy it themself. However, what if they miss a character at the beginning or end? What if they grab too much whitespace and you're not trimming? What if they are just confused of what to copy? There's too much room for error. A nice solution is to automatically copy this text to their clipboard. But where there's convenience, there's concern.

The Clipboard has security concerns

There's no concern when the user is in full control of the Clipboard. However, what happens when an app or program has programatic access to the Clipboard? I bet you can start to imagine some bad scenarios. What if an app secretly polls your Clipboard and sends the results to a server? That's potentially sensitive information at risk like passwords, bank accounts, or any long security token you never wanted to type yourself. How do we combat this?

SIGN UP!

One web topic. Every week. Sorry if you already have 😬

Security makes copy and paste weird on the web

Copy and paste has a strange history on the web. There's no real standard. Most browsers have settled on document.execCommand('copy') and document.execCommand('paste'). While that seems easy enough, there's some (justified) weirdness.

const result = document.executeCommand('copy');

If this is your first brush with document.execCommand('copy'), you might be wondering "Where is the text parameter?". You might have got all excited, tried running document.execCommand('paste'), and saw it do absolutely nothing.

Without some paperwork you can't just specify what text you want to add to the Clipboard. And you certainly can't just access whatever's on the clipboard at the time. There's some rules you need to follow.

The rules of Clipboard access with executeCommand('copy')

If you want to copy text with document.execCommand('copy'):

  1. The content must live in the DOM.
  2. The user needs to trigger the event (Firefox)
  3. The copied text is the user-selected text

Chrome doesn't require a user-triggered event, but it is required in Firefox.

index.js
const button = document.querySelector('#btnCopy');
button.addEventListener('click', event => {
  console.log(document.execCommand('copy'));
});

What if you want to copy text that's not in the DOM? You can inject it.

index.js
const button = document.querySelector('#btnCopy');
button.addEventListener('click', event => {
  const text = 'Hey look, this text is now in the DOM!';
  const input = document.createElement('input');
  document.body.appendChild(input);
  input.value = text;
  input.focus();
  input.select();
  console.log(document.execCommand('copy'));
});

If your text isn't in the DOM, then make it in the DOM. The snippet above creates a input element, adds it to the DOM, inserts the text into the element, focuses it, selects it, and then finally copies it.

What happens if you don't add the child to the DOM like in document.body.appendChild(input)? The text isn't copied. It can't just be a detached DOM node, it needs to be in the DOM.

If you want to read directly from the clipboard with document.execCommand('paste'), you can't. It doesn't work on Chrome, Firefox, Edge, or IE. To get data off the Clipboard you must listen to the paste event. (Which isn't supported in IE. The IE clipboard story is also strange. It's a property on the window and requires permission, but let's not get into that).

index.js
document.addEventListener('paste', event => {
  const text = event.clipboardData.getData('text/plain');
  console.log(text);
});

A user's paste action triggers a ClipboardEvent. On the event you have access to the clipboardData property, which is a DataTransfer object. Calling getData() with the proper format returns the copied text. Okay, I'm sorry. That was a lot of spec links.

This is great because you don't have ungranted access to the user's Clipboard. A user must issue the paste. However, there's a potential problem. The call to getData() is synchronous.

This poses a problem for you, the developer. What if they paste a massive base64-encoded image? Or some other insanely large amount of data? What if you do intense processing on this pasted data? This could block the main thread of the page, effectively freezing the page for your user.

Fortunately there's an up and coming solution. It's an entirely new way to read and write data from the Clipboard.

The Async Clipboard API

This new API has several improvements over our old friend document.execCommand('copy').

Note: This is Chrome only so far. This API is subject to change.

This new API is available on the Navigator object: navigator.clipboard

index.js
navigator.clipboard.writeText('whatever you need to copy').then(() => {
  console.log('Text copied')!            
});

The user is prompted to grant permission when you issue this command for the first time. Since this API is asynchronous the main thread is clear while we wait for the user's permission. If the API were synchronous, we'd be screwed.

To read from the Clipboard use readText():

index.js
navigator.clipboard.readText().then(text => {
  console.log(text);     
});

Just like before, if it's the first time then the user must grant permission before you can access the Clipboard. Remember, the Clipboard value is hard to trust and the data can be sensitive. It's still a good idea to ask the user to paste in a value where necessary.

index.js
document.addEventListener('paste', async event => {
  const text = await navigator.clipboard.readText();
  console.log(text);
});

This example is a big improvement over the synchronous getData() transfer method. The user must grant permission and you have async access. You're better protected against a large amount of text and it's easier to do more intensive processing on the pasted text.

Only the active tab has access to the clipboard

Users keep tabs open forever. Having unfettered access to the keyboard is still a bad idea. You could open example.com in a tab and leave it there for a week. Don't act like you haven't had a tab open for a week. During that time you'll have all sorts of data go in and out of your Clipboard. What if example.com polled the navigator.clipboard.readText() method? That would be mighty dangerous, but there's a safeguard.

Your site no longer has access to the Clipboard when the user switches to another tab. This is a great precaution, but it comes with an annoying debugging problem. When you open up the DevTools in Chrome, the DevTools itself becomes the active tab. The readText() or writeText() promise will reject and you'll be annoyed and be all like "This is why I don't use brand-new APIs". The trick is to defer the call until you can click back into the tab.

index.js
setTimeout(async () => {
  const text = await navigator.clipboard.readText();
  console.log(text);
}, 4000);

This isn't much better, but it'll work. This quirk isn't the only drawback of the Async Clipboard API.

The Async Clipboard API doesn't provide the user-selected text

Using document.execCommand('copy') will automatically copy the user's selected text. If you need that functionality, you'll have to get the selected text yourself and pass it in to writeText(). That will require a combination of the Selection API, the Range API, and some DOM traversal. You'll have to deal with combining text nodes across a range of DOM elements, and that's not fun.

Learn more about the Async Clipboard API

Jason Miller, who is a legend, wrote an amazing article on the Async Clipboard API. It's basically the standard resource at the moment.

Copy and paste responsibly

Clipboard access is a great tool for user experience, but it has its thorns. Some users carry sensitive data and some users bring malicious data. Make sure you handle user's data responsibly and prepare yourself for those nasty paste events.

THE HEAP

Links to articles I actually read

Web performance

Hacking user perception to make your websites and apps feel faster

medium.com/dev-channel/
Having great performance means understanding the user's perception of time. It's important to have a fast site, but animations and place holders go a long way. A great read by Mustafa Kurtuldu.

What Every Developer Must Know About HTTPS

troyhunt.com
Troy Hunt is a security expert that I've been following for years. He has a new course on PluralSight teaching the importance of HTTPS.

Speed is now a landing page factor for Google Search and Ads

developers.google.com/web
The title says it all. Fast sites are rewarded in Google Search. Use the proper tooling to understand the peformance of your site.

Demos

Big litle city

pissang.github.io
An amazing display of what you can do with WebGL. It's a planet of buildings, rivers, and roads based off real locations. An amazing work of art by Yi Shen.

Adding Particle Effects to DOM Elements with Canvas

css-tricks.com
Create amazing effects by combining regular HTML elements with Canvas. Creative use of the canvas by Zach Saucier.

Lazy box

codepen.io/chrisgannon
A beautiful display of SVG animation by Chris Gannon. The relection effect is really nice.

Angular

Drop 20K from your production Angular app

bendyworks.com/blog
Abraham Williams created a lighter version of the reflect-metadata polyfill. As you can guess, it results in a lighter Angular app.

How Node Is Helping to Propel Angular at Google

docs.google.com
Vikram Subramanian is the lead of Angular Universal. He recently gave a great presentation at Node Summit SF on how Google is using Angular Universal to help with major sites like Google Shopping Express.

(P)React

React for Designers

designcode.io
A few years back Meng To released Design Code, an online book about designing and building iOS apps. It was one of the best learning resources I have came across. Meng To has an amazing ability to teach designers code and developers design. I will be going through this course soon, even though I'm an experienced Preact developer.

guppy

github.com/joshwcomeau
A few weeks back Josh Comeau released a beautiful UI app for creating, running, building, and managing React apps. I'm a big fan of UI tooling for developers, and I'm also a big fan of the tool's design.

Fonts

Calibre

klim.co.nz
This is the title font for this site. It pairs well with a monospaced font like Menlo or Consolas. There's plenty of great monospaced fonts already on the user's machine.

Barna

typerepublic.com
Barna is a modern sans-serif font that's great for long form reading. I also like it it's bold set, which has potential as a heading.

Design

Refactoring UI

refactoringui.com
This is my new favorite YouTube Channel. Every so often Steve Schoger drops gems of design knowledge by refactoring an existing site. The beauty in each video lies in the small explanations Steve makes as he improves the site. This is a must watch.

pages.xyz

pages.xyz
A collection of well designed pages. Filter by different types. A great site for inspiration.

Machine Learning

A visual introduction to machine learning

r2d3.us
Want to start with Machine Learning? This visual guide is as informative as it gets. Amazing work by Stephanie Yee and Tony Chu.

Rules of Machine Learning

developers.google.com/machine-learning
Have you ever been confused by all the terms in an ML conversation? This article will clear them up for you and teach you how they're applied.

FEEDBACK

I need to hear from you. It's super important

Every week I ask you what was good and what might have sucked. I read each piece of feedback and work to incorporate it into the future editions of the newsletter. It's just a brief Google Form.

Survey link is here!

Contact / Privacy Policy