0 votes
by (360 points)
edited by

Hi everybody, 

I am having trouble using a from-validation-script I found someplace. I got this code working:

 <fieldset>
        <label for="name">Name</label>
        <input type="text" name="name" class="long" id="name" onblur="My.validateName(id, value)" autofocus/>
        <span id="nameError" style="display: none;">Please only use alphanumeric characters!</span>
        <label for="email">Email</label>
        <input type="text" name="email" class="long" id="email" onblur="My.validateEmail(id, value)" />
        <span id="emailError" style="display: none;">Please check your email adress!</span>
    </fieldset>

As expected, it calls the function My.validateEmail and My.validateName, which works perfectly.

My.validateName = function(id, value) {
			console.log('name: id: ' + id + ' value: ' + value);
			// Validation rule
			var re = /[A-Za-z -']$/;
			// Check input
			if (re.test(value)){
				// Style green
				document.getElementById(id).style.background ='#ccffcc';
				// Hide error prompt
				document.getElementById(id + 'Error').style.display = "none";
				State.variables.userName = value;
				State.variables.nameOK = true;
				return true;
			} else {
				// Style red
				document.getElementById(id).style.background ='#e35152';
				// Show error prompt
				document.getElementById(id + 'Error').style.display = "block";
				return false; 
			}
		};

Now I wanted to split the "name" field into two, "first name" and "surname" and went 

  <fieldset>
        <label for="firstName">Name</label>
        <input type="text" name="firstName" class="long" id="firstName" onblur="My.validateName(id, value)" autofocus/>
        <span id="nameError" style="display: none;">Please only use alphanumeric characters!</span>
		<label for="surname">Name</label>
        <input type="text" name="surname" class="long" id="surname" onblur="My.validateName(id, value)" autofocus/>
        <span id="nameError" style="display: none;">Please only use alphanumeric characters!</span>
        <label for="email">Email</label>
        <input type="text" name="email" class="long" id="email" onblur="My.validateEmail(id, value)" />
        <span id="emailError" style="display: none;">Please check your email adress!</span>
 </fieldset>

but I get "document.getElementById(...) is null." But I did assign individual ids for each of the <input>s, didn`t I?

Could somebody point me into the right direction?

 

 

 

1 Answer

0 votes
by (68.6k points)
edited by

You failed to also change the IDs of the two name error <span> elements.  They're both still IDed as nameError, when they should be firstNameError and surnameError.

by (159k points)

@richVIE

For future reference, manually assigned IDs of HTML elements on the same HTML page need to be unique.

by (360 points)
Thank you both very much!
by (360 points)
Sorry guys, can I bother you again?

Form field validation works great now thanks to your help. I am still having an issue when checking if all required fields were filled with appropiate information.

Thats my example: http://deutschdetektiv.net/exp/formvalidation.html

The functions called upon onblur of each input field set e.g. $mailOK, $phoneOK, etc. to true, which I check using the button before going to the next passage.

But it does only check for $mailOK. Could you give me another hint?
by (68.6k points)
It would help to see the other validation methods.

Beyond that, your name validation method's regular expression should probably be anchored on both ends, not simply at the end.
by (360 points)

Thank you  so much, TME, for getting back to me. So each of the four input fields calls its own validation function upon onblur. 

1. first name

My.validateFirstName = function(id, value) {
			console.log('name: id: ' + id + ' value: ' + value);
			// Validation rule
			var re = /^([ \u0430-\u044f\u00c0-\u01ffa-zђјљњћџA-Z'\-])+$/;
			// Check input
			if (re.test(value)){
				// Style green
				document.getElementById(id).style.background ='#ccffcc';
				// Hide error prompt
				document.getElementById(id + 'Error').style.display = "none";
				State.variables.userFirstname = value;
				State.variables.firstNameOK = true;
				return true;
			} else {
				// Style red
				document.getElementById(id).style.background ='#e35152';
				// Show error prompt
				document.getElementById(id + 'Error').style.display = "block";
				return false; 
			}
		};

2.surname

My.validateSurname = function(id, value) {
			console.log('name: id: ' + id + ' value: ' + value);
			// Validation rule
			var re = /^([ \u0430-\u044f\u00c0-\u01ffa-zђјљњћџA-Z'\-])+$/;
			// Check input
			if (re.test(value)){
				// Style green
				document.getElementById(id).style.background ='#ccffcc';
				// Hide error prompt
				document.getElementById(id + 'Error').style.display = "none";
				State.variables.userSurname = value;
				State.variables.surnameOK = true;
				return true;
			} else {
				// Style red
				document.getElementById(id).style.background ='#e35152';
				// Show error prompt
				document.getElementById(id + 'Error').style.display = "block";
				return false; 
			}
		};

As you can see, these two only differ in setting either State.variables.firstNameOK or  State.variables.surnameOK to true in case validation was successful. They also set the respective input value to a SugarCube variable.

3. Email

My.validateEmail = function(id, value) {
			console.log('email: id: ' + id + ' value: ' + value);
			var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
			if (re.test(value)) {
				document.getElementById(id).style.background ='#ccffcc';
				document.getElementById(id+'Error').style.display = "none";
				State.variables.userMail = value;
				State.variables.mailOK = true;
				return true;
			} else {
				document.getElementById(id).style.background ='#e35152';
				document.getElementById(id + 'Error').style.display = "block";
				return false;
			}
		};

4. Phone number

My.validateNumber = function(id, value) {
			console.log('name: id: ' + id + ' value: ' + value);
			// Validation rule
			var re = /^[0-9]+$/;
			// Check input
			if (re.test(value)){
				// Style green
				document.getElementById(id).style.background ='#ccffcc';
				// Hide error prompt
				document.getElementById(id + 'Error').style.display = "none";
				State.variables.userPhone = value;
				State.variables.phoneOK = true;
				return true;
			} else {
				// Style red
				document.getElementById(id).style.background ='#e35152';
				// Show error prompt
				document.getElementById(id + 'Error').style.display = "block";
				return false; 
			}
		};

Input field validation works as expected, what is causing me issues is the code within the <<button>> macro ath the bottom, which is expected to prevent from going to the next passage unless all four input fields have been adequately filled in.

<<button "Start!">>     
        <<if $firstNameOK eq false>>
            <<replace "#answer-error">>Please enter a valid first name!<</replace>>
		<<elseif $surnameOK eq false>>
            <<replace "#answer-error">>Please enter a valid surname!<</replace>>
		<<elseif $phoneOK eq false>>
            <<replace "#answer-error">>Please enter a valid first phone number!<</replace>>
        <<elseif $mailOK eq false>>
            <<replace "#answer-error">>Please enter a valid first email-adress!<</replace>>
        <<else>>  
            <<goto "next">>
        <</if>>
    <</button>> <span id="answer-error"></span>

It seems to determine phoneOK, firstNameOK and surnameOK to be TRUE, which they shouldn't be. As for your comment on anchoring the regex on both ends, I have to admit I do not understand what you mean.

Best regards,

richVIE

by (68.6k points)

Did you change the associated story variables in your initialization, and possibly elsewhere, when you made the name to firstName/Surname split?  A quick look at your example link shows that you probably did not—it certainly hasn't been properly updated, at least.

 

Additionally.  You have an issue which affects subsequent attempts to correctly fill out the form.  You're not setting the validation OK story variables to false when validation fails.  Even if you're initializing them to false, which you should be, you need to set them to false when validation has failed or someone could make an attempt with a valid value in one field, but some other issue, then on a subsequent attempt change the initially valid value to something invalid.  By not setting the OK variables to false when validation fails, you're allowing out-of-date OK values to pass their checks within the <<button>>.

 

As for your comment on anchoring the regex on both ends, I have to admit I do not understand what you mean.

Your original validation method example's regular expression looked like the following:

// Validation rule
var re = /[A-Za-z -']$/;

When it should have been something like:

// Validation rule
var re = /^[A-Za-z -']+$/;

In other words, you weren't anchoring the pattern to the start of the string via a leading ^.  Your last versions do have that, so it's something you've apparently already corrected.  (As I was writing this, I noticed that you also didn't match more than one character, something else you've also corrected in your last examples.)

 

PS: It's not idiomatic to test a boolean value against the boolean constants.  For example, things like these:

→ If true
<<if $firstNameOK eq true>>

→ If false
<<if $firstNameOK eq false>>

Would be better as:

→ If true
<<if $firstNameOK>>

→ If false
<<if not $firstNameOK>>

 

Additionally.  You should probably prefer the is/isnot operators to the eq/neq operators—see: <<if>> macro's TwineScript conditional operators section.

by (360 points)

Thank you, that was the problem! Just for future reference for other users, this is what I changed according to what TME told me.

1. initialize variables. StoryInit:

<<set $userFirstname to "">>\
<<set $userSurname to "">>
<<set $useruserPhone to "">>\
<<set $userMail to "">>\
<<set $firstNameOK to false>>\
<<set $surnameOK to false>>\
<<set $phoneOK to false>>\
<<set $mailOK to false>>\

2. Setting the respective OK variables to FALSE in the "else" part of each validation function:

} else {
	State.variables.mailOK = false;
	document.getElementById(id).style.background ='#e35152';
	document.getElementById(id + 'Error').style.display = "block";
	return false;
			}

Plus the suggested changes in the <<button>> elements.

 

Best,

 

richVIE

...