jquery validation plugin detects errors, but no messages appear, why not? - javascript

I'm using the jQuery Validator plugin 1.19.5 on a slightly large (but simple) form generated from a PDF by an online converter to html5
The form has a Submit button implemented as a button with onclick to a javascript function within the formviewer.js file that is part of the conversion to html5. If I open the form in Chrome 107.0.5304.107 Developer Tools, I can see that the Submit button goes to the following code that I added to the success branch of the function that handles the submit in formviewer.js:
success: function() {
const OSHform=$("form").eq(0);
if (OSHform.valid()) {
top.document.location.href = "/Adsentry/completed";
}
else {
alert("Fields did not validate, please fix errors and try again");
}
},
failure: function() {
alert("Form failed to submit, please try again")
}
In a separate script, I invoked validate() on the form element, passing it rules for the fields to validate.
var $j = jQuery;
var OSHform = $j("form");
OSHform.validate({
rules: {
"NAME OF DRIVER": "required",
"EMAIL": "required",
"EMAIL": "email",
"ADDRESS": "required"
}
});
If I omit required fields, or enter an invalid email address in an email field, the call to valid() returns false. And in fact, if I look at the input elements in the Elements tab, I can see that class="error" gets added, and if I correct the error it changes to class="valid". Additionally, with class="error", a label gets added for that element, also with class="error", and correcting the problem adds style="display:none;" to the label.
So everything is great, except that there is no text or message that goes with the label, so its presence/absence, or the presence/absence of display:none on it, has no effect on the normal display of the page.
I have tried stepping through the code in the debugger, but I'm afraid my javascript is so weak I can't really figure out what's going on to the extent of understanding why the messages are not being displayed.
You can play with it live here for the time being, but I can't promise to stop fiddling with it! There are currently only 3 required fields: Name of driver, Address, and Email. If they are all correct, the form submits as intended.

A little disappointed that this didn't even get any comments, let alone answers. On the other hand, it turned out the answer was exactly as anyone even slightly more experienced than me would likely have guessed: errors were being reported in HTML elements, but there was no CSS to put them in the right location on the page. The plugin seemed to be buggy in failing to produce default message text describing the errors; instead, it just produced message text that was simply the name attribute of the erroneous input element. But without appropriate CSS, that name attribute was output in the black strip at the bottom of the page, making it essentially invisible. It took a sharp eye to notice the sudden appearance of "fly specs" at the bottom of the page when clicking the submit button.
The plugin just inserts an HTML element into the DOM immediately following the bad input element. But the files generated from the PDF include a style sheet with selectors using the ID of each input element to give the input element absolute placement on the page. And simply inserting an element into the DOM as the next sibling of the input element, without a style, results in having it rendered at the bottom of the page. Even when I figured out that the lack of CSS was the problem, it took me a while to get something that worked: good old selector specificity in action. All of the input elements were placed using ID selectors with absolute position, and I could find no way to have the simple next-sibling relationship of the message to the input element cause the message to be rendered immediately after the input element. Although it made me feel "icky" to do it, the solution I came up with was to use jQuery to iterate over all the message elements with the "error" class, get the ID of the input element it was reporting, and then use $.css() to get the input element's effective top, left, and width style attributes. Then strip off the trailing "px", multiply by 1 to get a numeric value, add the width to the left numeric value, and specify new top and left attributes using $.css() on the message elements. This put the messages I defined in the messages sub-object of the object passed to the validate constructor appear in the right locations. It only remains a mystery why the default messages didn't appear instead of the names of the input elements for elements that were invalid.

Related

How to get this element from an email type input with Cypress

I need to validate the message that the user receives when entering an invalid email (without using #, for example) but the element does not exist in the DOM tree and so far I have not found any way to get this text.
Element to be caught
So far I've tried to treat the "alert" as a tooltip or popup but in no way that I found on the internet could I get this value
You can try CSS pseudo class for that. Below I'm giving one blog read from Gleb which highlight different techniques for HTML form validation:
Your code will be look more or less similar to this after that:
cy.get('#form-validation').within(() => {
cy.get('#email').invoke('prop', 'validationMessage')
.should('equal', 'YOUR TEXT IN THE ERROR MESSAGE...')
}
Gleb's Blog: https://glebbahmutov.com/blog/form-validation-in-cypress/

Appending input element to the DOM in safari transfers focus to the new input

I'm having trouble with the Safari browser, in that it, unlike other browsers including Chrome and Firefox, seems to be transferring focus to a newly created input field when it's appended to the DOM.
The use case is this:
I have a single email input field, into which users type an email (for sending invites). On the keyup event, we append a new email field underneath, to allow them to fill that one out too.
The logic (not exact code) is as follows:
$(document).on("keyup", ".invites input[type='email']", function(){
if("there isn't an empty email field, we'll add one"){
var parent = $(this).closest('wrapper');
var cloned_parent = parent.clone(); // we also remove content and classes here
$('.invites-container').append(cloned_parent);
}
})
It's at this point that the newly created element takes focus in Safari, but not in Chrome or Firefox. This is a problem, as the user may be typing an email address in the first input box, when the focus is snatched away, and all of a sudden they're typing in the second box, and so on. The end result is that multiple email fields are very quickly created just when typing a normal email address.
Strangley, I can't see much documentation around this difference - as appending a new element seems to be a very common function. I'm obviously missing something simple - can anyone advise what might be happening?
Things I've already tried:
Removing all javascript on the page, then cloning just the element
using .cloneNode() (no jquery) in the console - same issue, only in
safari
Removing all site css - same issue in safari
Cloning the input element itself, instead of the parent - same issue
Text inputs instead of email inputs - same issue
Please help!

Pointing to first field after validation

I have a webpage which has check-boxes, input fields, dropdowns etc.,
Mandatory conditions are checked using javascript. If anyone fails to fill these fields and press next button validation errors popup.
Now what I want to achieve is when someone fails to enter information in the mandatory fields, the cursor should go to the first field which caused the error.
Can anyone suggest me how to do this?
Add a class (something like input-error) for every invalid field. Then use something like:
var errors = document.querySelectorAll(".input-error");
if (errors.length > 0) {
errors[0].focus();
}
Here's an example: http://jsfiddle.net/NtHzV/1/
It really all depends on the structure of your code, how you're validating, what you're actually doing with validation, and what your HTML is.
At the same time, if you're doing something similar to my example, you might as well keep track of the first input with an error, then focus() it at the end of validation. Something like this:
http://jsfiddle.net/NtHzV/2/
UPDATE:
Bergi pointed out that querySelector might as well be used (instead of querySelectorAll) because you're only looking for the first input with errors. So here's an update:
var error_input = input_area.querySelector(".input-error");
if (error_input !== null) {
error_input.focus();
}
http://jsfiddle.net/NtHzV/3/
Here's specs on querySelector: https://developer.mozilla.org/en-US/docs/DOM/element.querySelector - Note that < IE8 does not support it.
The use of ".input-error" is because that is the CSS class selector, and will find the first (if any) element in a specific area with the class "input-error".
This line will focus the page on the element you specify. You should be able to implement this into your validation checks to focus on the bad elements.
document.getElementById("ID_Of_bad_field").focus();

LiveValidation js -- Change Text Message to Image

LiveValidation is a nice little inline form validation plugin.
I'd like to change the text confirmation message to an image.
The line that I edit is:
var message = paramsObj.failureMessage || "Must be included in the list!";
But when I change Must be... to img src=... it only displays the html text itself, not the image I'm calling.
I would investigate overriding the image css for the given form you want the validation image to show up for. I don't think this validation package will recognize an image URL, if I understand your attempt correctly. This would give you the picture message you want, while using the 'customization' point designed by this package's author.
LiveValidation objects use a few CSS classes to allow you to style up
the messages and the form fields based upon whether they are valid or
not.
LV_validation_message - the class that is added to all validation messages
LV_valid - the class that is added to a valid message
LV_invalid - the class that is added to an invalid message
LV_valid_field - the class that is added to a valid field
LV_invalid_filed - the class that is added to an invalid field
eg:
.LV_invalid {
/*color:#CC0000;*/
background-image:url('paper.gif');
}

How to hide an HTML input field with javascript

I need to hide a text input field with javascript. Changing its type attribute to hidden does not work in IE (security issue).
What would be the best way to do it?
Note: No jQuery or other lib can be assumed.
I assume you have to show and hide the text field dynamically based on changing conditions in the form, otherwise you'd just make it an <input type="hidden"... to begin with.
Keep your code that shows and hides the field as it is, but also catch the onsubmit event.
In the submit handler, get your text field via document.getElementById(...) (or by accessing document.forms[i]) and check to see whether or not it's hidden.
If it is hidden, create a new DOM node for an <input type="hidden" ...> field and add that node to the form, probably via myform.appendChild(...). You'll have to give it the name your server-side code expects. Copy the contents of the hidden text field into the newly created type=hidden field, then return from your submit handler, allowing the standard submit to continue.
You could also just un-hide the text field on submit, but you'd have to move it "off screen" also or the user would see it reappear during submit processing.
Try wrapping it in a div or span and then setting the display style to none when you want to hide it, and then to block (if you used a div) or inline (if you used a span) when you want to show it.
document.myform.myelement.style.display = 'none'
works as expected even in Internet Explorer.
The only way you can change it is before you append it to the DOM. You can make a new element and then replace the current one with it.
Look at replaceChild and createElement since you want to do manual DOM scripting. I assume you know what to do.
EDIT: "Hidden" fields as far as I know are sent. Have you checked whether they are? And you can also just do position:absolute; left:-9999em; to offset them.

Categories

Resources