Double Click to Select All Code

Child with a mac book mouse clicking that mouse with two fingers. Child with a mac book mouse clicking that mouse with two fingers.

When you want to display code, you are probably using PRE elements. The fact that these elements can contain markup makes them perfectly suited for syntax highlighting. Some plugins make it easier to copy the code using a button. Google Prettify has no such option. Let's see if we can make copying easier by providing a "double click to select all"-feature to our pre fields.

Getting a parent - the native way

In the past, I've used jQuery to do the heavy lifting in JavaScript. As browsers got better support for standard JavaScript API's this is often no longer needed. I'm a big fan of the closest function, so let's implement it in native JavaScript:

function getClosest(el, tagName) {
  tagName = tagName && tagName.toUpperCase();

  if (!tagName || !el)
    return null;

  do
    if (el.nodeName === tagName)
      return el;
  while (el = el.parentNode);

  return null;
}

Select All on Double Click

Let's use Range and document.getSelection to select all the text of the PRE element. On my site all elements contain CODE and SPAN elements that are needed for highlighting, so we use our getClosest function to find the PRE-parent:

document.addEventListener('dblclick', e => {
  let pre = getClosest(e.target, "PRE");
  if (pre) {
    let range = new Range();
    range.setStart(pre, 0);
    range.setEnd(pre, 1);
    document.getSelection().removeAllRanges();
    document.getSelection().addRange(range);
  }
});

The Range API has partial support in IE11.

Need something smaller?

The code above is pretty small -- only 504 bytes. But if you are really set on something smaller, you could minify it further to 327 bytes by applying UglifyJS on it:

!function(){let e=document;e.addEventListener("dblclick",t=>{let n=function(e,t){if(!(t=t&&t.toUpperCase())||!e)return null;do{if(e.nodeName===t)return e}while(e=e.parentNode);return null}(t.target,"PRE");if(n){let t=new Range;t.setStart(n,0),t.setEnd(n,1),e.getSelection().removeAllRanges(),e.getSelection().addRange(t)}})}();

It gets somewhat smaller, but it does not get more readable! 😀 Check how minification got rit of the getClosest method and just evaluates the result. Pretty neat!

Styling the selection

You might want to add some extra styling to the selection using CSS. The following CSS will add a gray background to the selection and keep the colors produced by the syntax highlighting:

pre::selection,
pre *::selection {
    background-color: #999;
}

pre::selection,
pre *::-moz-selection {
    background-color: #999;
}

Further reading

Improvements

2020-07-21: removed the jQuery dependency of the code and introduced the modern Range API.
2020-04-22: the original article was written. It can be found here in the Internet Archive or here.

expand_less