148

Simple question which I can't find the answer to:

How can I use JavaScript (or jQuery) to deselect any text which may be selected on a webpage?

E.G. user clicks and drags to highlight a bit of text - I want to have a function deselectAll() which clears this selection. How should I go about writing it?

Thanks for the help.

vsync
  • 118,978
  • 58
  • 307
  • 400
flatpickles
  • 2,198
  • 2
  • 15
  • 21

6 Answers6

247
if (window.getSelection) {
  if (window.getSelection().empty) {  // Chrome
    window.getSelection().empty();
  } else if (window.getSelection().removeAllRanges) {  // Firefox
    window.getSelection().removeAllRanges();
  }
} else if (document.selection) {  // IE?
  document.selection.empty();
}

Credit to Mr. Y.

Gert Grenander
  • 16,866
  • 6
  • 40
  • 43
  • 5
    This assumes that the existence of `document.selection` implies the existence of an `empty()` method of it. You've tested for the method in every other case, so you might as well test for `empty` in the final case too. – Tim Down Jul 05 '10 at 10:20
  • Used this within my [jquery.tableCheckbox.js](https://github.com/kerwitz/jquery.tablecheckbox/blob/master/jquery.tablecheckbox.js#L39-L46) plugin, thanks. – Marco Kerwitz Oct 07 '15 at 06:54
  • 2
    I have created a full working example based on your suggestion but adding some extras https://jsfiddle.net/mkrivan/hohx4nes/ The most important line is window.getSelection().addRange(document.createRange()); Without this IE does not deselect text in some conditions. And I have changed the ordering of the method detection. – Miklos Krivan May 21 '17 at 08:51
  • You save my day my friend! I was using scratchpad and when scratching the whole page was selected and with this good script I deselect my page before using scratchpad plugin. Basically it works! Thanks a lot! – Combine Jun 19 '17 at 09:01
  • 2
    I fount that `window.getSelection().removeAllRanges();` works fine in IE(edge) and Safari. – chile Jan 05 '18 at 06:58
  • this is good but how about on specific div... – Jenuel Ganawed Jul 10 '22 at 02:59
56

Best to test the features you want directly:

var sel = window.getSelection ? window.getSelection() : document.selection;
if (sel) {
    if (sel.removeAllRanges) {
        sel.removeAllRanges();
    } else if (sel.empty) {
        sel.empty();
    }
}
Tim Down
  • 318,141
  • 75
  • 454
  • 536
17

2021 answer

  • removeAllRanges() is supported by most browsers, except Safari on macOS or iOS.

  • empty() is an alias for removeAllRanges() and supported by all browsers, including very old ones, with the exception of IE. This alias is defined in the specification, so should be safe to rely on.

Conclusion

Just use getSelection().empty(). There is no need for helper functions, nested ternary ifs, constructors, and whatnot Ninja banzai from the other answers. Perhaps needed ten years ago, but not any more.

If you really need IE support you can test for document.selection:

(window.getSelection ? window.getSelection() : document.selection).empty()

(not tested on IE)

Martin Tournoij
  • 26,737
  • 24
  • 105
  • 146
  • 1
    `removeAllRanges()` is supported in Safari in both macOS and iOS, unless it's been removed, which I highly doubt since it's widely used. I agree that it's safe to remove the checks for really old IE (<= 8) now but otherwise the situation hasn't changed substantially in the last ten years. My suggestion would be `window.getSelection().removeAllRanges()`, which will also cover you in IE back to version 9. Note also that in some (rare) situations, `window.getSelection()` can return `null`, so it may be worth checking for this, hence some of the ninja banzai whatnot in other answers. – Tim Down Jan 04 '21 at 09:55
16

State of De-selection Affairs 2014

I did some research of my own. Here's the function I wrote and am using these days:

(function deselect(){
  var selection = ('getSelection' in window)
    ? window.getSelection()
    : ('selection' in document)
      ? document.selection
      : null;
  if ('removeAllRanges' in selection) selection.removeAllRanges();
  else if ('empty' in selection) selection.empty();
})();

Basically, getSelection().removeAllRanges() is currently supported by all modern browsers (including IE9+). This is clearly the correct method moving forward.

Compatibility issues accounted for:

  • Old versions of Chrome and Safari used getSelection().empty()
  • IE8 and below used document.selection.empty()

Update

It's probably a good idea to wrap up this selection functionality for re-use.

function ScSelection(){
  var sel=this;
  var selection = sel.selection = 
    'getSelection' in window
      ? window.getSelection()
      : 'selection' in document
        ? document.selection
        : null;
  sel.deselect = function(){
    if ('removeAllRanges' in selection) selection.removeAllRanges();
    else if ('empty' in selection) selection.empty();
    return sel; // chainable :)
  };
  sel.getParentElement = function(){
    if ('anchorNode' in selection) return selection.anchorNode.parentElement;
    else return selection.createRange().parentElement();
  };
}

// use it
var sel = new ScSelection;
var $parentSection = $(sel.getParentElement()).closest('section');
sel.deselect();

I've made this a community wiki so that you people can add functionality to this, or update things as the standards evolve.

ChaseMoskal
  • 7,151
  • 5
  • 37
  • 50
  • 7
    That is doing the same as my answer. Nothing has changed in 4 years. – Tim Down Feb 23 '15 at 16:13
  • 4
    Horrible. Not only did you literally steal the implementation from another poster, but you completely trashed it syntactically. – kamelkev Mar 25 '16 at 20:48
1

Here's the accepted answer, but in two lines of code:

var selection = window.getSelection ? window.getSelection() : document.selection ? document.selection : null;
if(!!selection) selection.empty ? selection.empty() : selection.removeAllRanges();

The only check I don't do is for the existence of removeAllRanges - but AFAIK there is no browser that has either window.getSelection or document.selection but doesn't have either a .empty or .removeAllRanges for that property.

Grinn
  • 5,370
  • 38
  • 51
-3

add this to your script to prevent right clicking and text selecting.

Exceptions can be added to var 'om'.

var d=document,om=['input','textarea','select'];;
function ie(){if(d.all){(mg);return false;}}function mz(e){if(d.layers||(d.getElementById&&!d.all)){if(e.which==2||e.which==3){(mg);return false;}}}if(d.layers){d.captureEvents(Event.mousedown);d.onmousedown=mz;}else{d.onmouseup=mz;d.oncontextmenu=ie;}d.oncontextmenu=new Function('return false');om=om.join('|');function ds(e){if(om.indexOf(e.target.tagName.toLowerCase())==-1);return false;}function rn(){return true;}if(typeof d.onselectstart!='undefined')d.onselectstart=new Function('return false');else{d.onmousedown=ds;d.onmouseup=rn;}
user2180104
  • 25
  • 1
  • 2
  • 1
    That's not the question that was asked. It's pretty clear that selection is required, but the OP is looking for a way to deselect the region programmatically when it's no longer required. – Auspex Jun 08 '21 at 15:46