How do Dojo ValidationTextArea widgets get highlighted when invalid? - javascript

I am trying to create a custom Dojo ValidationIdBox widget that inherits from ValidationTextBox. My custom widget will add async duplicate ID checking with a back-end server.
I sub-classed dijit.form.ValidationTextBox and modified two methods: isValid() and validate(). However, I can't get the validation to fully work. The widget catches and highlights problems like missing required input. It even catches when there is a duplicate ID (the tooltip appears), but it fails to highlight the field as expected.
I have tried to isolate my problem with a simplified code snippet below. It is mostly the origininal Dojo code with some minor modifications. My general strategy is to let the widget validate as a regular ValidationTextBox, then test for a duplicate ID. I modified isValid() to have two modes: plain validation and validation with uniqueness check. Currently, the uniqueness test intentionally always fails.
In a similar fashion, I modified validate() to do its normal thing, then do some additional processing if normal validation succeeds but the validation with uniqueness test fails. I tried to mirror the same logic as when the ValidationTextBox is in an error state, but the same effects are not mirrored: The 'ID not available' tooltip appears, but the red outline with exclamation mark does not appear.
I examined ValidationTextBox's code, but I cannot figure out how that special styling is triggered... can someone explain how ValidationTextArea works? Specifically I'm not quite sure how this._maskValidSubsetError, aria-invalid, and this.state are used.
(Also sometimes, I want the tooltip to appear, but not the red styling. Like to show when AJAX duplicate ID check request is processing.)
// If ValidationTextBoxValidates
isValid: function(isFocused, requireUnique) {
if (typeof requireUnique === 'undefined') requireUnique = false;
var isValid = this.inherited(arguments);
var isUnique = false;
return (requireUnique ? (isValid && isUnique) : isValid);
},
validate: function(/*Boolean*/ isFocused){
// summary:
// Called by oninit, onblur, and onkeypress.
// description:
// Show missing or invalid messages if appropriate, and highlight textbox field.
// tags:
// protected
var message = "";
var isValid = this.disabled || this.isValid(isFocused);
if(isValid){ this._maskValidSubsetError = true; }
var isEmpty = this._isEmpty(this.textbox.value);
var isValidSubset = !isValid && isFocused && this._isValidSubset();
this._set("state", isValid ? "" : (((((!this._hasBeenBlurred || isFocused) && isEmpty) || isValidSubset) && this._maskValidSubsetError) ? "Incomplete" : "Error"));
this.focusNode.setAttribute("aria-invalid", isValid ? "false" : "true");
if(this.state == "Error"){
this._maskValidSubsetError = isFocused && isValidSubset; // we want the error to show up after a blur and refocus
message = this.getErrorMessage(isFocused);
}else if(this.state == "Incomplete"){
message = this.getPromptMessage(isFocused); // show the prompt whenever the value is not yet complete
this._maskValidSubsetError = !this._hasBeenBlurred || isFocused; // no Incomplete warnings while focused
}else if(isEmpty){
message = this.getPromptMessage(isFocused); // show the prompt whenever there's no error and no text
}
/// Begin custom widget code
if (isValid && !this.isValid(isFocused, true) ) {
isValid = false;
var isValidSubset = !isValid && isFocused && this._isValidSubset();
this._maskValidSubsetError = isFocused && isValidSubset; // we want the error to show up after a blur and refocus
message = 'ID not available';
this.focusNode.setAttribute("aria-invalid", isValid ? "false" : "true");
}
/// End custom widget code
this.set("message", message);
return isValid;
},

might be missing the obvious, hidden amongst a cloud of inline &&|| ;)))))
The point in the blur/keypress mechanism is that the tooltip will only be visible on the box that is currently shown, hence _maskValid
Have you tried this.set("state", this.isUnique() ? "" : "Error"); ??
Widgets are Stateful and the .set might just do the trick, firing an event or publish a topic

Related

How to focus on first input of error in js where return false is not working

I have multiple input fields and if three fields showing error then focus goes on the last error field.
How to set focus on the first error field and so on. I tried return false; and it is not working. preventDefault() also not working.
This is my js code for the name field and the rest of the field validation is the same as this name field except validation rules.
if (name.length < 1) {
$('#name_error').text(NAME_ERROR);
$('#name').focus();
error = true;
// return false; not working
} else {
var regEx = /^[A-Za-z ]+$/;
var validName = regEx.test(name);
if (!validName) {
$('#name_error').text(INVALID_NAME_ERROR);
$('#name').focus();
error = true;
// return false; not working
} else {
$('#name_error').text('');
error = false;
}
}
Option 1 - Add class to the fields with error and then you can use below code to focus the first error element.
$('.error-class').first().focus()
Option 2 - Create a variable of top of the function and store the ID of the first error field in that. At the end of the validation rules trigger focus for the element ID stored in a variable.

Check if input is of type "text/number/email/etc"?

I need to check with Javascript (not jQuery) if the given input element is writable by the user using the keyboard.
I'd like to exclude checkboxes, radios, buttons, resets, submits, image and so on.
Is there a simple way to do it without list all the input types?
This is my current code now:
if (element.getAttribute === undefined) {
return false;
}
var eTag = element.tagName;
var eType = element.getAttribute('type');
var isTextInput = (eTag === 'INPUT' || eTag === 'TEXTAREA') && ( eType !== null || eType === 'text' || eType === 'password');
var isEnabledInput = element.disabled === false && element.readOnly === false;
var isContentEditable = ( element.contentEditable && element.contentEditable === true );
// stop for enabled text inputs, selects and contentEditable areas
return (isTextInput && isEnabledInput) || eType === 'SELECT' || isContentEditable;
Logically the && ( eType !== null || eType === 'text' || eType === 'password'); is not enough to check them all.
Posting this as an answer because fixes the problem, but it's not strictly what I'm asking for.
I'm still waiting for a cleaner solution.
var notTextual = [
'button',
'checkbox',
'hidden',
'image',
'radio',
'reset',
'submit'
];
if (element.getAttribute === undefined) {
return false;
}
var eTag = element.tagName;
var eType = element.getAttribute('type');
var isTextInput = (eTag === 'INPUT' || eTag === 'TEXTAREA') && !notTextual.contains(eType);
var isEnabledInput = element.disabled === false && element.readOnly === false;
var isContentEditable = ( element.contentEditable && element.contentEditable === true );
// stop for enabled text inputs, selects and contentEditable areas
return (isTextInput && isEnabledInput) || eType === 'SELECT' || isContentEditable;
If you wanna call a function depending on the type of input, create an array with the wished types of input, another with the types function and do a loop.
function GetInputType(e){ // e = element
var Types=[
"text",
"password"
],
Attr=e.getAttribute("type"),
Actions=[
function(){alert("It's text.")},
function(){alert("It's password.")}
],
Call=function(){alert("Unknown type.")};
for(var i=0,l=Types.length;i<l;i++){
!function(i){
if(Attr==Types[i])
Call=Actions[i];
else break
}(i)
}
Call()
}
I think you're going to need to write something yourself. You're asking for more specific business logic than you think.
text is text.
number is text but the input must be 0-9, and decimal.
password is text-input, black circles or similar shown on screen.
Radio buttons are certainly keyboard-inputtable. Text won't display, but that's also true for password. Also the input is essentially "yes" or "no," but that's just a restriction on what keyboard inputs do, just like number is a restriction on what keyboard inputs do.
So you want something like...
the keyboard can input at least some of the time...
and text must display on screen unless it's a password...
and more input should be accepted than just a "space" or "enter" as in radio button or checkbox
That's not a standard HTML modifier, or standard jQuery, or anything. That's your own business logic.
I know this is a non-answer but I think there's good reason to believe you won't find what you're looking for out-of-the-box somewhere. It depends on your own application's logic, exactly what you mean by "text."

submit function - display a warning message

I'm trying to display a warning message when a user types certain text into an input box. The problem is I only want to return false one time so the user can submit the form on the second click even if they don't change the text. I've tried adding a counter but jquery is not remembering the count on a second sumbit click. What is the best way to go about this?
if (email.val().indexOf("gmail") > -1))
{
$('input[name=email]').css('border-color','red');
$("#submit").after('<p>Error - Do you want to use a gmail account?</p>');
return false;
}
I would use a flag to determine if they have already tried to submit, and if they haven't, then you give them the warning and return false:
var triedSubmit = false;
$(/* Your jQuery Object */).click(function() {
if (email.val().indexOf("gmail") > -1))
{
if (!triedSubmit){
$('input[name=email]').css('border-color','red');
$("#submit").after('<p>Error - Do you want to use a gmail account?</p>');
triedSubmit = true;
return false;
}
}
}
Just set up some kind of flag
var flags = {}; // in some higher scope
// then later, in your verification function
if (email.val().indexOf("gmail") > -1 && !flags.warnedGmail) {
$('input[name=email]').css('border-color','red');
$("#submit").after('<p>Error - Do you want to use a gmail account?</p>');
flags.warnedGmail = true;
return false;
}
Why don't you put a class on your text box and remove it in the first failure? Thus when you look for it with jQuery a second time you won't be able to find it it and won't be able to apply the rule. I implmented it like so:
var submit = function()
{
var email = $('.emailFirstTry')
if (email.length > 0 && email.val().indexOf("gmail") > -1)
{
$('input[name=email]').css('border-color','red');
$("#submit").text('Error - Do you want to use a gmail account');
$('.emailFirstTry').removeClass('emailFirstTry');
return false;
}
$('input[name=email]').css('border-color','none');
$("#submit").text('Success!');
return true;
};
You can see it in action on this fiddle right here: http://jsfiddle.net/ozrevulsion/39wjbwcr/
Hope the helps :)

Controlling the submission

I'm trying to stop the submit if an error exists and go through the submission if no error exist.
This is just a section of the code. Regex works correctly, also the error texts were showing up too. The thing is that now I'm trying to control the submit proccess and due to an error (console is not showing up anything) the error text is not showing up and the submission is just going through even if an input error exists.
There is a mistake that I cannot figure out (No jquery please)
var sub = document.querySelector("#register input[type='submit']");//the submit botton
var err_text_1 = "First name must be filled out!";
sub.onsubmit = function(){
if (first_name == null || first_name == "") {
err_holder_1.innerHTML = err_text_1;
return false;
}
else {
err_holder_1.style.display = "none";
}
}
To prevent submit add event in the function and return false like so:
sub.onsubmit = function (event) {
// Will prevent submit
event.preventDefault();
return false;
};
Also select the form you are submitting not the button itself. So:
var sub = document.getElementById('ActionForm');
Hope this helps.
You need to select the form like
var sub = document.querySelector("#register");//If register is your form id Not input[type='submit']

How to reset the oninput() html event after first use?

I have a db search form with multiple fields. Two of them, job_id and job_desc, I want to be disabled when the other one is used and vice versa. I have written a small Javascript function to do this.
Here is my form code:
<input type="text" id="job_id" oninput="input('job_id','job_desc')" onblur="blur('job_id','job_desc')">
<textarea id="job_desc" oninput="input('job_desc','job_id')" onblur="blur('job_desc','job_id')"></textarea>
Here is my Javascript code:
function input(a,b)
{
var a = document.getElementById(a);
var b = document.getElementById(b);
alert("This will disable "+b); // Let the user know we are disabling the other field
b.value = ""; // Empty the other field
b.disabled = true; // Disable the other field
}
function blur(a,b)
{
var a = document.getElementById(a);
var b = document.getElementById(b);
if(a.value = "") // If the field is empty...
{
b.disabled = false; // Enable the other field.
}
}
I have these problems:
1) For some reason my second field does not re-enable once the first field is empty and blurred. This leads me to believe the onblur() event is not working.
2) Once I type in some text, I get the alert once and it's all good. However, when I empty the field and the re-input some text, the alert doesn't trigger a second time. How do I reset the oninput() event?
Here is my fiddle: fiddle
You can use the "onkeyup" event instead of the other events:
The HTML Code would be :
<input id="job_id" onkeyup="input('job_id','job_desc')">
<br>
<textarea id="job_desc" onkeyup="input('job_desc','job_id')"></textarea>
And the JS funciton :
function input(a, b) {
var ea = document.getElementById(a); // We put A in a variable
var eb = document.getElementById(b); // We put B in a variable
if(ea.value != ""){ // If the element have a value / text in it
if(!eb.disabled) // we check if the other element is disabled, if not, we trigger the alert
alert("This will disable " + b); // Let the user know we are disabling the other field
eb.value = ""; // Empty the other field
eb.disabled = true; // Disable the other field
}else{ // if the element's value is empty (which means that we have erased the existing value)
alert(b + " is now enabled"); // Let the user know we are enabling the other field
eb.disabled = false; // We re-enable the field
}
}
It will work fine on all the browsers..
I hope it will help you !
Besides the solution provided, the reason your code did not work is it was conflicting with a native blur() function on the window object, and so your blur call was calling that instead of your own blur function. You need to change its name.
Another issue once you fix that is in
if(a.value = "") // If the field is empty...
it should have two = signs for comparison.
if(a.value == "") // If the field is empty...
Demo at http://jsfiddle.net/q11m3ahz/6/

Categories

Resources