BearPanther.com

Easy Text Selection in Mobile Safari

Introduction

user

bear


LATEST POSTS

Using jsformat with Sublime Text 26th July, 2014

There are many d3 demos like this but this one is mine 08th June, 2014

Blog

Easy Text Selection in Mobile Safari

Posted on .

Selecting text in Mobile Safari is not as easy as it could/should be. This is one of those things that is strangely hard compared to what we’re used to with a mouse. What’s the solution? JavaScript, of course. Before getting into the specifics, here’s a simple demo to show where this post is going.

Some background: I was building a BearPanther URL shortener and wanted to be able to easily select the newly created short URL or look at a list of existing short URLs and easily select one of those. No “long press” or double taps. I played with a couple different approaches and settled on a technique included in a CSS Ninja post titled Playing with the clipboard in iOS safari. The heart of it boils down to two things:

  • add contentEditable=”true” to the node you want to copy
  • use a selection and range to select text

The simple page to demo this technique shows both. That page uses plain old JavaScript so it probably doesn’t work everywhere. But if you’re reading this, you’re probably a web developer and shouldn’t have a problem running it in Chrome or Safari. Please do not tell me that it doesn’t work in IE8. To really see why this is useful, run it in Safari on an iPhone.

As for the code, it’s simple. Get a reference to the element where you want to easily select text:

var easy = document.querySelector(".easySelect");

Set up a click event listener:

easy.addEventListener("click", select);

Add the required attribute and set a select in the event listener callback:

function select(evt) {
  // a textNode is required to set a selection on mobile safari
  // nodeType values:  https://developer.mozilla.org/en-US/docs/Web/API/Node.nodeType
  if ( evt.target.firstChild.nodeType !== 3 ) {
    console.log("Unable to select text, firstChild is not a textNode.");
    return;
  }
  var el = evt.target;
  // for this to work on mobile safari, contentEditable needs to be true
  if ( !isEditable(el) ) {
    el.setAttribute("contentEditable", true);
  }
  // current selection
  var sel = window.getSelection();
  // create a range:  
  // https://developer.mozilla.org/en-US/docs/Web/API/document.createRange
  var range = document.createRange();
  // use firstChild as range expects a textNode, not an elementNode
  range.setStart(el.firstChild, 0);
  range.setEnd(el.firstChild, el.innerHTML.length);
  sel.removeAllRanges();
  sel.addRange(range);
}

And that’s it. There’s a bit more going on in the actual demo page code and comments so I encourage you to take a closer look.

Comments
user

Author Andrew

Posted at 3:32 pm July 6, 2013.

This is great solution, but there is an issue that makes in unusable. After cuntentEditable is enabled the keyboard appears. Did you find a way to fix that?

Reply
    user

    Author bear

    Posted at 2:55 pm September 12, 2013.

    The keyboard popping up isn’t ideal, but I don’t see a way to avoid it. I’ll take a single tap + keyboard popping up over tap + drag to beginning of text + drag to end of text.

    Reply
user

Author askapache

Posted at 10:06 am April 2, 2014.

The key thing for me to get it to work was to add the contentEditable=”true” bit… Thank you very much!

Reply
user

Author Lihze

Posted at 11:35 pm October 10, 2014.

Nice Post :).

Plz help me to solve this problem…
I want users to be able to select text, but I don’t want the copy/define menu to show up. Either that, or I’d like to be able to modify that menu with my own options. Is there a way to do this?

Reply

Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

View Comments (5) ...