Extended demonstrations of cursor maintenance

This page demonstrates three approaches to maintaining cursor position in a text input field that formats its contents in real time. Whenever the text is formatted, the cursor position must be reconsidered. The goal of cursor maintenance is to place the cursor in a position that minimizes user surprise.

The problem of cursor maintenance is discussed in an article. Source code is available in a repository.

Meta approach

In the meta approach, we reimplement a format by applying elementary operations to a text-with-cursor object. The object moves the cursor in a predictable manner for each elementary operation.

Below we demonstrate the meta approach with two formats, commatize and trimify.

Commatize is defined for text consisting of digits and commas. Input strings containing other characters are rejected by a validation function that runs before the formatter. Commatize displays a non-negative integer with commas separating groups of three digits.

Trimify is applicable to any text. The input is not validated before formatting. Trimify removes whitespace from the beginning of the text, then condenses all other whitespace sequences to one space each.

commatize

trimify

Retrospective approach

In retrospective cursor maintenance, we calculate a new cursor position by comparing the formatted text to the raw text and cursor position. We do not reimplement the format or examine what it does in general. We only consider the current formatting instance.

You can define a format to be used in the following input field by inserting a JavaScript function into the code area below. The function must take a string argument and return a string.

The retrospective scoring formula used here is called frequency ratios. It computes the ratios of individual character frequencies to the left and right of the cursor in the original text, then tries to achieve similar ratios in the formatted text using a least-squares fit.

user-defined

Layer approach

In the layer approach, we define a ranked sequence of character sets for a format. We extract a text layer by scanning the text for members of a character set. At each text position, we calculate the ratio of layer characters to the left of the position divided by the total number of layer characters.

Initially we consider the first layer and try to find a position in the formatted text where the ratio is as close as possible to that of the cursor in the raw text. If several positions have equally close ratios, we shrink the range of candidate positions and move on to the next layer. If all layers are exhausted, we choose either the leftmost or rightmost position in the final candidate range. The choice of left or right is a fixed value in the layer configuration.

As with the retrospective approach, you can define your own format in the code area below. You can modify the character sets and the tie-breaking direction in the fields between the input area and the code area. Each character set is defined by a JavaScript regular expression.

user-defined

layer configuration:
tie-breaker: left right