Forum Discussion
RichardMulcahy
2 years agoCommunity Member
Any JavaScript Experts Out There?
 I found this sample code on the web, but it's not working for me. I'm trying to limit the number of characters a user can enter (for example 5), and if they exceed then I show a layer with an error m...
Nathan_Hilliard
2 years agoCommunity Member
I came across a mutation observer script that will successfully monitor the input value in the current version of Storyline. I inserted it into your original script (the one in the SL file, after fixing the quote character errors), and it worked as expected.
The script includes two event handlers; one for user inputs and one for programatic changes to the input value.
Two things became apparent.
- Users input changes don't seem to fire events, but the programatic changes can still be captured.
- Your selection method for the inputs creates 4 input references. Two (0 and 1) are under the .acc-shadow-dom class, and do not generate events. The remining two (2 and 3) do generate mutation events. Your maxChars array, as implemented, therefore needs 4 entries.
The updated script is as follows
//function below borrowed from 
//https://stackoverflow.com/questions/32383349/detect-input-value-change-with-mutationobserver#61975440
function observeElement(element, property, callback, delay = 0) {
    let elementPrototype = Object.getPrototypeOf(element);
    if (elementPrototype.hasOwnProperty(property)) {
        let descriptor = Object.getOwnPropertyDescriptor(elementPrototype, property);
        Object.defineProperty(element, property, {
            get: function() {
                return descriptor.get.apply(this, arguments);
            },
            set: function () {
                let oldValue = this[property];
                descriptor.set.apply(this, arguments);
                let newValue = this[property];
                if (typeof callback == "function") {
                    setTimeout(callback.bind(this, oldValue, newValue), delay);
                }
                return newValue;
            }
        });
    }
}
//------------------------------------------------------------------------------
//Excerpt from your original script
function inputLengthCheck(textField, index) {
	var maxLength = maxChars[index];
	console.log("Idx",index, "maxLen", maxLength);
	if (textField.value.length > maxLength) {
		textField.value = textField.value.slice(0, maxLength);
		player.SetVar("ShowLayer", true);
	} else {
		player.SetVar("ShowLayer", false);
	}
}
//------------------------------------------------------------------------------
//The body of your original script
var textFields = document.querySelectorAll("input[type='text']");
//Note: in your current selection method, there are actually 4 imput boxes.
//The two that function with the events are 2 and 3.
//0 and 1 are part of the shadow-dom (class = acc-shadow=dom)
var maxChars = [4,4,4,4];
var player = GetPlayer();
textFields.forEach(function(textField, index) {
	
	//Note: this event handler does not get called on user input in Storyline
	textField.addEventListener("input", function () {
    console.log("Input value changed via UI. New value: '%s'", this.value);
	
		//do length check
		inputLengthCheck(textField, index);
	});
	
	//Note: This event handler does get called in Storyline
	observeElement(textField, "value", function (oldValue, newValue) {
    console.log("Input value changed via API. Value changed from '%s' to '%s'", oldValue, newValue);
		//do length check
		inputLengthCheck(textField, index);
	});
});
Related Content
- 9 months ago