Ali
Ali

Reputation: 118

How to add a cursor/text position indicator to a <textarea> controlled by javascript?

I am making a typewriter like website (here) that uses a textarea and javascript (from button clicks) to add/remove from the textarea.

The next thing I want to add is an indicator to show where the next update (insert/remove) will be so I guess its always at the of the textarea value.

The key details that clash with other solutions are

This is how I insert characters

function insert(char) {
    document.getElementById("textarea").value += char
    update()
}

to the textarea + a button

<textarea id="textarea" class="textarea" disabled>
</textarea>

<a onclick="insert('1')"> 
    <div class="letterbox">
        <p class="typewritter">1</p>
    </div> 
</a>

(btw I know I spelled typewriter wrong on the website and will fix that later)

Upvotes: 3

Views: 800

Answers (4)

atanay
atanay

Reputation: 174

If you want to make a custom insertion point (the blinking line) you can do that by adding and removing a chosen symbol ('|' for example) from the text with an interval. Perhaps something like this would do:

const insertionSymbol = '|';
const blinkInterval = 1000; // time in ms between insertion point updates
let blinking = true; // whether the insertion line is hidden
let textarea = document.getElementById('textarea');
setInterval(function() {
    if(blinking) {
        textarea.value += insertionSymbol;
    } else {
        textarea.value = textarea.value.slice(0,-1);
    }
    blinking = !blinking;
}, blinkInterval);

that would require you to change the insert and delete functions:

function insert(char) {
    if(blinking) {
        textarea.value += char;
    } else {
        // inserting the character before the insertion point by removing the insertion point temporarily 
        textarea.value = textarea.value.slice(0,-1) + char + insertionSymbol; 
    }
}
function delete() {
    if(blinking) {
        textarea.value = textarea.slice(0,-1);
    } else {
        // deleting the character before the insertion point by removing the insertion point temporarily 
        textarea.value = textarea.value.slice(0,-2) + insertionSymbol; 
    }
}

This idea can be expanded. for example, if you want to add a insertion point cool-down (i.e. change the insertion point to stay visible for some time after an update, like you see in most text editors), you can change the interval to run every millisecond, and add a timer for the next update. like this:

// ... all the variable definitions like before
let timer = blinkInterval;
setInterval(function() {
    timer --;
    if(timer == 0) {
        if(blinking) {
            textarea.value += insertionSymbol;
        } else {
            textarea.value = textarea.value.slice(0,-1);
        }
        blinking = !blinking;
        timer = blinkInterval;
    }
}, 1);
function insert(char) {
    if(blinking) {
        blinking = false;
        textarea.value += char + insertionSymbol;
    } else {
        // inserting the character before the insertion point by removing the insertion point temporarily 
        textarea.value = textarea.value.slice(0,-1) + char + insertionSymbol; 
    }
    timer = blinkInterval;
}
function delete() {
    if(blinking) {
        blinking = false;
        textarea.value = textarea.slice(0,-1) + insertionSymbol;
    } else {
        // deleting the character before the insertion point by removing the insertion point temporarily 
        textarea.value = textarea.value.slice(0,-2) + insertionSymbol; 
    }
    timer = blinkInterval;
}

Note: I'm writing the code blindly (I didn't run it to see if it works) so I'm sorry in advance for any mistakes.

Upvotes: 3

oguzhancerit
oguzhancerit

Reputation: 1572

I think overriding textarea attributes is meaningless. The indicator that you want is already in it's characteristic.

Remove the disabled tag from your textarea and just block the keyboard pressing with the below code snippet. [because not using keyboard typing is your feature]

document.onkeydown = function (e)  {
  return false;
} 

If you want to you can bind the function to focus action of the textarea.

Upvotes: 3

Agamemnon Katradis
Agamemnon Katradis

Reputation: 165

My suggestion on this would be to have the textarea active, NOT disabled and always on focus. This way you will have the blinking effect you want. Then have a pointer-events:none css on the textarea so no one can click on it and you have the blink you want. So my steps would be:

  1. Remove disabled from textarea
  2. Add pointer-events:none css rule to the textarea
  3. On the update() function I observe add either a focus or a click event so the textarea gets focus on each insert()

Upvotes: 2

Julien Ripet
Julien Ripet

Reputation: 558

One way to do it would be to have a loop running non stop (with a requestAnimationFrame maybe ?) to add and remove a | character every other second, which would simulate the usual text position indicator you have inside most text areas

Upvotes: 1

Related Questions