npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@koddsson/textarea-caret

v4.0.1

Published

(x, y) coordinates of the caret in a textarea or input type='text'

Downloads

192

Readme

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