Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

After clicking on selected text, window selection is not giving updated range

After double click, selection range can be obtained correctly on onclick event but when I again click on the selected text then updated selection range should be returned by window selection but this is not happening. Can anybody tell me if this is a bug in javascript selection or they have made it this way. And what could be the solution to get the updated range apart from timer.

<div id="xyz" contenteditable="true">Hello world</div>
<span class="status">Selected text : </span>

javascript code :

function yourFunction() {
    if (window.getSelection) {
         var selectionRange = window.getSelection();
         $('.status').text(selectionRange.toString());
    }
}

$('#xyz').click(function () {
    $('.status').text('Mouse click');
    yourFunction();
})

Example here

like image 331
mukesh Kumar Avatar asked Dec 25 '13 18:12

mukesh Kumar


2 Answers

You fiddle is working just fine. But, yes sometimes when you do selections in quick succession, then it fails to register the click.

The problem really lies in the way you have implemented it on click on the text input itself. A click event is generated when a mouseup follows a mousedown. A selection happens when you mousedown then drag and then mouseup.

If you separate out the selection retrieval then this problem won't occur.

See this updated fiddle: http://jsfiddle.net/zRr4s/21/

Here, the selection retrieval is donw on a button click, instead of the input itself.

i.e., instead of:

$('#xyz').click(function (e) { ...

using this:

$('#btn').click(function () { ...

where, btn is:

<input id="btn" type="button" value="get selection" />

Hope that helps.

Update:

If you insist on handling event only on the input, then listening mouseup would be better option:

See this fiddle: http://jsfiddle.net/zRr4s/22/

$('#xyz').on("mouseup", function (e) { ...

Update 2:

To handle your requirement of in-context click, you will have to first clear the selection. For this to happen you will have to handle mousedown. So, that will defeat your purpose of having only one handler. Anyway,

You updated fiddle: http://jsfiddle.net/zRr4s/29/

And, this is how you do it:

$('#xyz').on("mousedown", function () {
    clearTheSelection();
});

Where clearTheSelection is another function:

function clearTheSelection() {
    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();
    }
}

The complete code for the above function taken from this answer: https://stackoverflow.com/a/3169849/1355315

Hope that completes all your problems.

like image 113
Abhitalks Avatar answered Sep 25 '22 02:09

Abhitalks


The fiddle provided in the question works fine in Edge and IE11 but doesn't work in Chrome. I found a trick to make it work everywhere. Add the following event handler in addition to the click handler you already have:

$(document).on("selectionchange", function () {
    yourFunction();
});

Some notes:

  1. selectionchange is a document level event, you cannot bind it to specific element (but you can find out whether you need to handle it within the event handler)

  2. Handling selectionchange without also handling click doesn't work well in Edge and IE11

According to MDN, browser support is good enough: https://developer.mozilla.org/en-US/docs/Web/API/Document/selectionchange_event

like image 39
johnnyjob Avatar answered Sep 23 '22 02:09

johnnyjob