Giter Site home page Giter Site logo

textarea-caret-position's Introduction

Textarea Caret Position

Get the top and left coordinates of the caret in a <textarea> or <input type="text">, in pixels. Useful for textarea autocompletes like GitHub or Twitter, or for single-line autocompletes like the name drop-down in Twitter or Facebook's search or the company dropdown on Google Finance.

How it's done: a faux <div> is created off-screen and styled exactly like the textarea or input. Then, the text of the element up to the caret is copied into the div and a <span> is inserted right after it. Then, the text content of the span is set to the remainder of the text in the <textarea>, in order to faithfully reproduce the wrapping in the faux div (because wrapping can push the currently typed word onto the next line). The same is done for the input to simplify the code, though it makes no difference. Finally, the span's offset within the textarea or input is returned.

Demo

Check out the JSFiddle or the test.html.

Features

  • supports <textarea>s and <input type="text"> elements
  • pixel precision with any combination of paddings, margins, borders, heights vs. line-heights etc.
  • keyboard, mouse support and touch support
  • no dependencies whatsoever
  • browser compatibility: Chrome, Safari, Firefox (despite two bugs it has), Opera, IE9+
  • supports any font family and size, as well as text-transforms
  • not confused by horizontal or vertical scrollbars in the textarea
  • supports hard returns, tabs (except on IE) and consecutive spaces in the text
  • correct position on lines longer than the columns in the text area
  • no problem getting the correct position when the input text is scrolled (i.e. the first visible character is no longer the first in the text)
  • no "ghost" position in the empty space at the end of a line when wrapping long words in a <textarea>
  • RTL (right-to-left) support

Example

var getCaretCoordinates = require('textarea-caret');

document.querySelector('textarea').addEventListener('input', function () {
  var caret = getCaretCoordinates(this, this.selectionEnd);
  console.log('(top, left, height) = (%s, %s, %s)', caret.top, caret.left, caret.height);
})

API

getCaretCoordinates(element, position)

  • element is the DOM element, either an <input type="text"> or textarea

  • position is an integer indicating the location of the caret. Most often you'll want to pass this.selectionStart or this.selectionEnd. This way, the library isn't opinionated about what the caret is.

The function returns a caret coordinates object of the form {top: , left: , height: }, where:

  • top and left are the offsets in pixels from the upper-left corner of the element and (or presumably the upper-right, but this hasn't been tested), and
  • height is the height of the caret - useful to calculate the bottom of the caret.

Known issues

  • Off-by-one edge cases with spaces at the end of lines in <textarea>s (#29). This may be a bug in how browsers render the caret.
  • Edge case with selecting from right to left strings longer than the <input> (#40). The caret position can be quite off in this case.
  • Tab characters in <textarea>s aren't supported in IE9 (#14)

Dependencies

None.

TODO

  • Add tests.
  • Consider adding IE-specific code if it avoids the necessity of creating the mirror div and might fix #14.
  • Test IE8 support with currentStyle.

Implementation notes

For the same textarea of 25 rows and 40 columns, Chrome 33, Firefox 27 and IE9 returned completely different values for computed.width, textarea.offsetWidth, and textarea.clientWidth. Here, computed is getComputedStyle(textarea):

Chrome 33

  • computed.width : "240px" = the text itself, no borders, no padding, no scrollbars
  • textarea.clientWidth: 280 = computed.width + padding-left + padding-right
  • textarea.offsetWidth: 327 = clientWidth + scrollbar (15px) + border-left + border-right

IE 9: scrollbar looks 16px, the text itself in the text area is 224px wide

  • computed.width: "241.37px" = text only + sub-pixel scrollbar? (1.37px)
  • textarea.clientWidth: 264
  • textarea.offsetWidth: 313

Firefox 27

  • computed.width: "265.667px"
  • textarea.clientWidth: 249 - the only browser where textarea.clientWidth < computed.width
  • textarea.offsetWidth: 338

Contributors

textarea-caret-position's People

Contributors

ashubham avatar chemzqm avatar dandv avatar danrpts avatar elierotenberg avatar jgerigmeyer avatar jonathanong avatar mottie avatar rso avatar yury-dymov avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

textarea-caret-position's Issues

Position is shifted with CSS wrap as break-word

Noticed this in case of textarea regarding the incorrect caret coordinates produced when the word breaks into a new line due to CSS property of overflow-wrap having value as break-word.

Peek 2020-12-30 23-00

Notify maintainers of similar libraries

We've uncovered some cool tricks on getting the (x, y) position of the caret in a textarea and in the true spirit of open source, it would be nice to notify the maintainers of similar libraries. Some may choose to honorably deprecate their libraries and point users to this one; others might want to incorporate what we've learned and increase the quality of their solutions; and hopefully others will contribute to textarea-caret-position as well (we still have some bugs!).

This issue will also serve as a list of how this component stacks against others in scope and features.

StackOverflow list of questions on textarea:

StackOverflow questions re. <input type="text">

Google Code projects:

Firefox edge cases

super off with firefox. i don't know what's going on - seems like a ff bug since the padding is outside the scroll area vs. webkit where the padding is inside the scroll area (correct imo)
screen shot 2014-03-13 at 3 04 26 pm

Bad positioning on android

Hello!
The positioning of the red div is wrong on my android phone (my browser is google chrome). Here is a screenshot:
2014-06-19 18 14 28

Update jsFiddle link

The Fiddle provided as a demo does not update automatically. I created the demo which uses rawgit to pull in the current index.js. And it uses the debug mode ๐Ÿ˜

http://jsfiddle.net/aFPA7/167/

One issue I did notice is that in Firefox, that if you press the "Tidy" button at the top and run the demo, all the tabs are removed and that really long line of content no longer has an accurate caret position.

Using tidy actually works better in MS Edge since the scrollbar disappears - probably the same issue as mentioned in #21.

Package Maintenance/Ping

Hi!

First off, thank you so much for writing this and maintaining it for years. I work at Oscar health and this is helping us implement powerful and great UI features!

That being said, the last time this package was updated was two years ago!
https://www.npmjs.com/package/textarea-caret

I am having some issues, that appear to be known where there are bugs when the text area begins to scroll/overflow:
Ex: #51

This is just one of many open bugs (and 5 open PRs).

Is there any plan to continue maintenance on this/fix these bugs? If not I'd be interesting in seeing how we can continue on this project and put it in a place where it can continue to be updated/used. Seems like a lot of people like/need this!

It doesn't feel great to write code around a lib (a nice lib!), and it seems it shouldn't be a ton of work to get in some of these bug fixes.

Thank you,
Jake

IE11

doesn't seem to be working on it. i think it's the scroll bars.

Suggest `text-rendering: geometricPrecision`

Thanks for this great library!

Seems like WebKit and Gecko are too smart and alter textarea text rendering for speed purposes, making it different from div rendering, unless the text-rendering CSS property is set to geometricPrecision.

It might be good to either forcibly set it (though I don't know if that will work) or recommend in the README that it be set by the user in their textarea CSS, e.g.:

textarea { text-rendering: geometricPrecision }

What I experienced was different line spacing between a textarea and the hidden div even though lineHeight was identical.

h/t https://stackoverflow.com/questions/25260908/mismatch-in-text-width-between-div-and-textarea

Use with with white-space nowrap

Hi,

FIrst I'd like to thank you for this great library, however it does have an annoying bug with white-space: nowrap.
Indeed, when I attempt to use this library on a textarea generated by React that has white-space: nowrap, the library returns incorrect positions when the text is longer than the width of the textarea.

Advantages relative to getBoundingClientRect?

This project sounds great but I can't tell why this is better than window.getSelection().getRangeAt(0).getBoundingClientRect()? Are there cases where that fails but this library works?

If so, I think that it would be great to cover this in the readme.

Option to return coords of caret bottom

Hi!

If you want to display a popup/tooltip below caret, you have to account for text field's line height.

Retrieving a calculated value of a DOM element's line height is non-trivial. There's a library that implements a hack similar to what subj does for caret position. Unfortunately, it is unreliable: on Chrome 57 it would report double line height, but single on Firefox 51.

Subj has all the framework required to detect the bottom of the caret. Essentially, the top of the caret + line height.

There's already an undocumented options argument which could be used to pass a bottom flag.

Position outside input after scrolling from right to left

  1. Type text longer than the input
  2. Using the mouse, select from right to left, so the text scrolls to its start
  3. With the selection active, click within the text in the input

The caret will be displayed outside the input, where the text would end if the input were longer.

input select from right to left

Test/demo lags one keystroke behind

Following up on issue #2 - the component works remarkably well, compared to the most popular plugin in the space.

One issue I found is that it lags one operation behind the last keystroke, as seen in the animation below:

textarea-caret-position
Testing was done in Chrome 33. Hope there's an easy fix for the issue, so we can switch to this instead of beviz's one that depends on jQuery.

Publish latest to npm.

It seems the last time this package was published to npm was an year ago, and some changes have gone in since then.

The package.json version is currently 3.1.0 and the npm published is 3.0.2. It would be great if someone with access could publish the latest, for consumers like me to be able to use.

undefined font-family for textarea

Its not really a bug as such,
but not having a defined font for the text area meant that the mirror div ended up with a different font to that of the textarea. (Using IE11) the textarea font by default is monospace, but by not being defined its wasn't picked up from the properties, so wasn't applied to the div, and the div just used the body font.

Bad position at the end of line before wrapped word in Firefox

Environment: Mozilla Firefox 42
Situation:
Several words in line, the last one long enough to be put into a new line. Navigate to the end of the last non-wrapped word and go once to the right.
Problem:
Real caret stayed in the first line, after some "imaginary Firefox space", while library caret was at the beginning of the next line.

In my opinion it's more of a Firefox bug, since the position of the real caret is indeed weird. But since this library should find position of caret and not a position of optimal placement of caret, I file it as bug.

Demonstration of described situation is here:
selection_041

Is this project still being maintained?

There are five pending PR that seem pretty reasonable and well implemented.
Is there a reason not to merge them?

I'd be really interested in using this project (and contribute to it) but I got that sort of ghost-y vibe from it.
Just making sure I'm wrong :)

Using it in electron app.

At first, I have to say this component help me a lot! thx!

But, when I using it in an electron app with polymer, I want to build an element which can notice the position in the textarea, the only way to use textarea-caret-position is to require this component, but use script tag.

Can you give some global variable to set the way how I require this, but not just use isBrowser?:-D

I hope you can get my point.:-D

Get Absolute distance from the top

Is there any way to achieve the 'absolute' distance from the top.

Upon increasing the textinput size and repositioning the caret to the top , it returns the distance including the one that got hidden due to scrollbar in the textinput .

For more clarity :

Screenshot from 2020-12-01 20-07-20

This returns the value as 1928 px (as it also considers the area hidden above , due to scrollbar) . Is there any method to retrieve the caret position from the top in this case . (Here , maybe around 10-15px) ?

Safari and Chrome position issue

I essentially copy pasted the code into one of my projects, and it seems that for textarea, there are cases when the red caret goes to the next line, while the black caret is one character away from going to the next line.
screen shot 2019-03-08 at 2 54 21 am

Publish latest version to NPM

Hiya!

The latest version available through npm is v0.1.1. When attempting to use the library as given in the example in the README, v0.1.1 returns undefined.

I noticed that a lot of work had been done since then, and it looks like the latest version is 3.0.0.

As a workaround, I directly installed from this git repo (npm install component/textarea-caret-position --save).

Could you please publish the latest version to npm?

Caret disappears when dash character inserted on very long text in text box

Using the test.html sample provided in the docs (https://rawgit.com/component/textarea-caret-position/master/test/index.html
), in the manual testing ground on top of page enter the following:

MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM-M

image

Notice the red display for the caret disappears when you add 'M' after a '-' characted. Remove the 'M' at the end and displays OK again. Only seems to happen when you cause it to scroll with quite a few letters in the text box. Doesnt appear to happen if you have a few characters.

Only found this as it looks to be causing this issue on Github Desktop: desktop/desktop#6806. I've debugged it there and it seems to return an invalid left value for the caret once the dash is added after calling getCaretCoordinates

Found using Chrome 105.0.5195.127

EDIT: Debugged the code from testarea-caret-position and it seems span.offsetLeft/offsetTop is invalid once a dash is added with a new character

image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.