2

How can I select programmatically from A(x1,y1) to B(x2,y2) ?

x1, y1, x2, y2 are pixel coordinates. I searched a lot and in all functions I found, we had to specify a specific tag and then it selects its content.

user1365010
  • 3,185
  • 8
  • 24
  • 43
  • 7
    Can you expand a bit more on what you're trying to do? What are A and B, for instance? – T.J. Crowder Jun 25 '12 at 14:23
  • 3
    I'm sure you can make this question a little better and explain with more details what you're trying to do. – MilkyWayJoe Jun 25 '12 at 14:24
  • @T.J.Crowder There is not really A and B. When you drag with your mouse and select a text it's from (30,43) to (343,234) for exemple. And I want to have the selection you would have with these numbers – user1365010 Jun 25 '12 at 14:26
  • 1
    are you talking about highlighting text in an input box? this is done by character, not by pixel. – jbabey Jun 25 '12 at 14:26
  • @jbabey I mean selecting like this fiddle: http://jsfiddle.net/edelman/KcX6A/339/ – user1365010 Jun 25 '12 at 14:26
  • So A and B are pixel coordinates? – Tim Down Jun 25 '12 at 14:27
  • @user1365010 if you read the documentation for the methods that the fiddle is using to highlight text, i'm sure you can figure out how to tweak it to accept `start` and `end` values. (Hint: [start](https://developer.mozilla.org/en/DOM/range.setStart) and [end](https://developer.mozilla.org/en/DOM/range.setEnd)) – jbabey Jun 25 '12 at 14:28
  • I'd suggest adding a bit of detail to the question for searchability etc. – Tim Down Jun 25 '12 at 14:29
  • @jbabey the selection start and end aren't really specified as coordinates. They just say *select the content of this tag*. – user1365010 Jun 25 '12 at 14:30
  • @user1365010 they will never be specified by pixel coordinates, as i said earlier. highlighted is by text node or by characters in text nodes. – jbabey Jun 25 '12 at 14:31
  • possible duplicate of [Highlight text range using JavaScript](http://stackoverflow.com/questions/6240139/highlight-text-range-using-javascript) – jbabey Jun 25 '12 at 14:35
  • @jbabey: No, it's not a duplicate. It's about creating a text selection from pixel coordinates, not character offsets or highlighting. – Tim Down Jun 25 '12 at 14:56

2 Answers2

18

You can do this in current versions of all browsers. These browsers have at least one of the following:

  • The standards-based approach, implemented by Firefox >= 20, from the CSSOM View spec: document.caretPositionFromPoint()
  • WebKit's proprietary version of the same: document.caretRangeFromPoint().
  • IE's proprietary TextRange object, which has a moveToPoint() method that takes pixel coordinates. However, it seems that moveToPoint(), which is used in all version of IE, can be buggy (see here and here, for example); I've simply been lucky that has worked in all the documents I've used it in.

However, Mozilla does not yet implement any of these and neither does Opera, so this can't be done in those browsers yet.

Firefox 20 and later supports document.caretPositionFromPoint(). Opera 15 supports document.caretRangeFromPoint()

Here's some example code. It works in IE 5+, WebKit from around 2010 onwards, Firefox >= 20 and Opera >= 15.

Live demo: http://jsfiddle.net/timdown/ABjQP/

Code:

function createSelectionFromPoint(startX, startY, endX, endY) {
    var doc = document;
    var start, end, range = null;
    if (typeof doc.caretPositionFromPoint != "undefined") {
        start = doc.caretPositionFromPoint(startX, startY);
        end = doc.caretPositionFromPoint(endX, endY);
        range = doc.createRange();
        range.setStart(start.offsetNode, start.offset);
        range.setEnd(end.offsetNode, end.offset);
    } else if (typeof doc.caretRangeFromPoint != "undefined") {
        start = doc.caretRangeFromPoint(startX, startY);
        end = doc.caretRangeFromPoint(endX, endY);
        range = doc.createRange();
        range.setStart(start.startContainer, start.startOffset);
        range.setEnd(end.startContainer, end.startOffset);
    }
    if (range !== null && typeof window.getSelection != "undefined") {
        var sel = window.getSelection();
        sel.removeAllRanges();
        sel.addRange(range);
    } else if (typeof doc.body.createTextRange != "undefined") {
        range = doc.body.createTextRange();
        range.moveToPoint(startX, startY);
        var endRange = range.duplicate();
        endRange.moveToPoint(endX, endY);
        range.setEndPoint("EndToEnd", endRange);
        range.select();
    }
}
Tim Down
  • 318,141
  • 75
  • 454
  • 536
  • @user1365010: You HTML can't see the `createSelectionFromPoint()` function because it's defined inside a `load` handler. Here's an update: http://jsfiddle.net/jz7Jx/2/ – Tim Down Jun 25 '12 at 15:00
  • No the bug is because I was in firefox :( There is really no way to do this for firefox ? – user1365010 Jun 25 '12 at 15:00
  • @user1365010: Well, it wasn't working in Chrome either because of the problem I mentioned :) I can't think of an easy way to do this in Firefox off the top of my head. – Tim Down Jun 25 '12 at 15:02
  • I will accept your answer, but if you find a way working with the current version of firefox (and opera?) I'll give you a bounty of 100 :D – user1365010 Jun 25 '12 at 15:06
  • The only way of doing it in Firefox that occurred to me was a slightly complicated way of doing it using trial and error and the `getBoundingClientRect()` method of ranges. Here's an answer that uses this (I haven't tested it though, and it doesn't look quite right): http://stackoverflow.com/a/3710561 – Tim Down Jun 25 '12 at 15:08
  • @user1365010: Actually, this answer is better: http://stackoverflow.com/a/9603270/96100. I may incorporate it into mine later. – Tim Down Jun 26 '12 at 09:04
  • @vasanth: That answer uses the same technique as my answer, namnely `doc.caretRangeFromPoint()`, but without the fallbacks for other browsers. – Tim Down Aug 27 '14 at 16:52
  • Is there any way to make it work with page scroll? So that dy distance between startY and endY could be more than screen height – emvaized May 19 '21 at 04:46
1

For Firefox or Opera there is a little workaround. This set the caret at the first position of an element:

console.log("moz or opera doesn't support caret by position so we have a workaround");
var range = doc.createRange();
var element = doc.elementFromPoint(startX, startY);
range.setStart(element, 0);
Yannick Blondeau
  • 9,465
  • 8
  • 52
  • 74
oliver
  • 11
  • 1