8

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

Abhitalks
  • 27,721
  • 5
  • 58
  • 81
mukesh Kumar
  • 103
  • 1
  • 8

2 Answers2

4

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.

Community
  • 1
  • 1
Abhitalks
  • 27,721
  • 5
  • 58
  • 81
  • I think you misunderstood my intent. Actually I want to have one listener which can immediately give me the range as soon as click completed. window selection refreshes its selection range when you click on the button not just after you finishes your clicking. (in case of clicking on a selected text) – mukesh Kumar Dec 26 '13 at 11:56
  • @mukeshKumar: there you go. updated the answer. handle *mouseup* instead of *click*. – Abhitalks Dec 26 '13 at 12:00
  • updated fiedel is still giving the wrong result. step to reproduce: 1. select some text 2. click on selected text – mukesh Kumar Dec 26 '13 at 12:24
  • when you select some text say "Hello" then you can see this word in status div. Again when you click between 'H' and 'ello' you can see that same word "Hello" is getting displayed while nothing should get displayed as nothing has been selected. – mukesh Kumar Dec 26 '13 at 16:13
  • @mukeshKumar: that is not a problem. that is how it works. unless the context is lost, the selection will remain. you are not moving from the current selection and hence context is still active. if you just click outside the context then it will be lost. – Abhitalks Dec 26 '13 at 16:23
  • According to my application this is a problem. So can you suggest any solution for this ??? – mukesh Kumar Dec 27 '13 at 05:25
  • @mukeshKumar: well, that's the way it works. you can't change that. – Abhitalks Dec 27 '13 at 06:28
  • I understand dude but there must be some alternative solution to achieve that. – mukesh Kumar Dec 27 '13 at 06:49
  • @mukeshKumar: there you go. updated the answer. hope that helps. – Abhitalks Dec 27 '13 at 07:41
  • I really appreciates your effort but I just want to tell you that I have also tried the same thing and it was working fine on chrome and mozila but it created side effect on IE. On IE you can not select whole line/paragraph by double/tripple click. – mukesh Kumar Dec 27 '13 at 08:29
  • @mukeshKumar: of course i can select entire line/para by triple-click on ie. – Abhitalks Dec 27 '13 at 08:39
  • If you are trying http://jsfiddle.net/zRr4s/29/ then it is not abe to fire even mousedown event. Can you share the fiedel where you tried plz ?? – mukesh Kumar Dec 27 '13 at 09:53
  • @mukeshKumar: Ok got it now. IE is actually behaving strangely. Sorry, mate I won't be able to help you further on this. – Abhitalks Dec 27 '13 at 10:17
  • Clearing the selection - you are a true gentleman and a scholar. Thank you! – Vinay Oct 26 '17 at 23:45
  • There are two problems with this solution. 1) It takes a risky path of changing built-in browser text selection logic within mouse event handlers; 2) It still fails if your text selection was changed not by clicking (example: select some text, then type anything). – johnnyjob May 28 '20 at 11:55
1

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

johnnyjob
  • 380
  • 1
  • 9