Limit number of characters in a text input field using Javascript

My boss wanted to be able to limit text input in a Storyline course. She wanted to be able to limit the number of characters, and show this limit in a real-time updated text field below the text input field, not unlike what is typical on many website forms. This type of functionality with a text input control is not possible out-of-the-box.

The Text input control, when created, is linked to a newly-created variable that gets defined when the control is created. This created variable holds the value of the text input field. [You can change this variable later if you want.] If I have a value in a variable, I can check for its length with JavaScript.

One irritating issue though, is that this linked variable does not update until the text input field loses focus. And there is no good way to force the text input field to lose focus, other than to have the user click somewhere else on the screen. This does not lend itself to real-time updating or limiting the number of characters, since any check can only happen after you are done typing and click somewhere else on the screen.

So I looked into ways around this bottleneck. Using JavaScript, I could watch for key events and add (or delete) each character to the text entry value as it gets added. I could also look at the length of the variable and test it against a maximum length. Once I captured and added these key values, I could update the field, limit it to the maximum number established, and report these numbers by using embedded variable references.

The variables I use in this example, which is included as an attachment to this discussion, are listed here:

TextEntry - a string that is linked to the text input field

Text_max - a number, which I set to a default of 140 (characters - like Twitter - but it can be set to any number you like, either as a global default or per slide)

Text_num - a number which is set to the current length of the TextEntry string

ValueStorage_01 - a generic string variable that stores the value of TextEntry when leaving the slide. [It resets TextEntry when coming back into the slide, to allow for saving this value as you go along in the course, and also re-using TextEntry in other slides.]

TextEntry is the variable linked to the text input field. Text_num and Text_max can show status in a text control ("%Text_num% of %Text_max%") on the timeline.

The one problem in all this is that there is no generic key event that looks for any key press. There are key events for single values or Shift/Ctrl/Alt key combinations. So I had to account for ALL key combinations in my triggers, which resulted in around 100 separate individual triggers to simulate regular keyboard input! Ye gods. [If there was a way to pass in a parameter to a key event I could have used one JavaScript execution to do this. If anyone out there knows how to do this, please pass it along!]

[Digression: I guess I could have set a variable with a key value, then hit a generic JavaScript trigger by watching for the change of value in that variable, but that would preclude having the same value occur twice in a row (reiteration), and deleting more than once in a row...I just talked my way out of this digression.]

Here is an example of the typical JavaScript key input. This example captures typing the 1 ("one") key:


var thePlayer = GetPlayer();
var theChar = thePlayer.GetVar("TextEntry");
theChar = theChar + "1";
var theMax = thePlayer.GetVar("Text_max");
var theLength = theChar.length;
if (theLength <= theMax) {
  thePlayer.SetVar("Text_num",String(theLength));
  thePlayer.SetVar("TextEntry",theChar);
}

Here is an example of deleting characters, used with the Delete and Backspace keys:


var thePlayer = GetPlayer();
var theChar = thePlayer.GetVar("TextEntry");
var theLength = theChar.length;
theChar = theChar.substring(0,theLength-1);
theLength = theChar.length;
thePlayer.SetVar("Text_num",String(theLength));
thePlayer.SetVar("TextEntry",theChar);

I did find that the backslash character did not play well here, so I left it out. I tried to escape it, but it didn't do any good. [There is a way to include it in a string as hex, but I didn't bother. I know, I'm lazy.] The backslash character was the only lower-order ASCII I left out of this example. All upper and lower case alpha-numeric characters and special characters such as !@#$%^&*()_+-=;':",./<>? are included, including the space (" ") and newline characters.

A couple of notes: The input caret ("|") visible in the text input field is not used here. In fact I have cut off direct editing of the text input field by covering it with a transparent shape. Since the field itself does not update until it loses focus, direct editing would thwart my entire set-up. Which also means we've lost the ability to cut and paste here. Perhaps a person could set up a way to click on the transparent covering field, and include an off field surface that would toggle between direct editing and this JavaScript construct I've built. [This might be phase two of this project.]

Also: the keyboard keys do not reiterate (continues to add/delete the same character) if you hold them down, at least in the Flash-published version. However, I believe that the HTML5-published version DOES reiterate. This might be a limitation of the Flash player or the implementation of it in Storyline.

Of course, being that it is using JavaScript, you can't preview this in the Storyline's development environment - you have to publish it to see it work.

I'll do a feature request for Storyline version 3 to see if they can include this functionality without having to use JavaScript. You have to admit, needing to use 100-some triggers to do a function that could have been done by having a generic key event is kind of a long way to go to make something work!

6 Replies
Mark Ramsey

Thanks Ashley!

The attachment is up here now.

I did put in a feature request.

Steve, in my feature request I also asked about having a way to restrict input to a subset of characters. For instance, if you just want to enter a phone number, allow only numbers, a dash, parentheses, maybe the hash symbol etc. I realize this is going toward field validation, which again, is probably best dealt with JavaScript. But you still need to be able to test the variable in real time, and not wait for the text input field to lose focus in order to update that variable.

Maybe if they added just a generic key event that covered any key event, just this could have simplified (and shortened) my code considerably. With this generic key event, they could let you plug in a value that could be sent along as a parameter. [Or a range of values, say a delineated text string that you could parse into an array at the JavaScript level. Or while we're wishing, some JSON.] 

[I rewrote portions of the original posting to make it easier to understand.]