I've written a custom form validation script, but for some reason, wrapping input[type=text] elements in <div class="inputWrapper" /> stops me from preventing input[type=submit]'s default setting.
Here's the relevant code:
$("input[type=text]").wrap("<div class=\"inputWrapper\" />");
Is breaking:
$("input[type=submit]").click(function(event) {
event.preventDefault();
});
Why is this happening? If you need a more full script, let me know, and I'll just post the whole thing.
Alright, so for some reason, disabling that line of code allows .preventDefault on the input[type=submit] to work, but if I just use
// wrap inputs
$("input[type=text]").wrap("<div class=\"inputWrapper\" />");
// validate on form submit
$("input[type=submit]").click(function(event) {
event.preventDefault();
});
It works fine. So here's the full script, what could cause this weirdness?
$(document).ready(function() {
// wrap inputs
$("input[type=text]").wrap("<div class=\"inputWrapper\" />");
$("textarea").wrap("<div class=\"inputWrapper\" />");
// validate text inputs on un-focus
$("input[type=text].required").blur(function() {
if ($(this).hasClass("error")) {
// do nothing
} else if ($(this).val() === "") {
$(this).addClass("error");
$(this).parent(".inputWrapper").append("<div class=\"errorPopup\">" + $(this).attr("placeholder") + "</div>");
}
});
// validate textareas on un-focus
$("textarea.required").blur(function() {
if ($(this).hasClass("error")) {
// do nothing
} else if ($(this).val() === "") {
$(this).addClass("error");
$(this).parent(".inputWrapper").append("<div class=\"errorPopup\">" + $(this).attr("placeholder") + "</div>");
}
});
// validate on form submit
$("input[type=submit]").click(function(event) {
event.preventDefault();
// check fields
$(this).parent("form").children("input.required").each(function() {
// check textboxes
if ($(this + "[type=text]")) {
if (!$(this).val()) {
$(this).addClass("error");
};
};
// end textboxes
// check textareas
$(this).parent("form").children("textarea.required").each(function() {
if (!$(this).val()) {
$(this).addClass("error");
};
});
// end textareas
// check checkboxes and radio buttons
if ($(this).is(":checkbox") || $(this).is(":radio")) {
var inputName = $(this).attr("name");
if (!$("input[name=" + inputName + "]").is(":checked")) {
var inputId = $(this).attr("id");
$("label[for=" + inputId + "]").addClass("error");
};
};
// end checkboxes and radio buttons
});
// end fields
// submit form
var errorCheck = $(this).parent("form").children(".error").length > 0;
if (errorCheck == 0) {
$(this).parent("form").submit();
} else {
alert("You didn't fill out one or more fields. Please review the form.");
window.location = "#top";
};
// end submit form
});
// clear errors
$("input.required").each(function() {
// clear textboxes
if ($(this + "[type=text]")) {
$(this).keypress(function() {
$(this).removeClass("error");
$(this).next(".errorPopup").remove();
});
};
// end textboxes
// clear textareas
$("textarea.required").each(function() {
$(this).keypress(function() {
$(this).removeClass("error");
$(this).next(".errorPopup").remove();
});
});
// end textareas
// check checkboxes and radio buttons
if ($(this).is(":checkbox") || $(this).is(":radio")) {
var inputName = $(this).attr("name");
var labelFor = $(this).attr("id");
$(this).click(function() {
$("input[name=" + inputName + "]").each(function() {
var labelFor = $(this).attr("id");
$("label[for=" + labelFor + "]").removeClass("error");
});
});
};
// end checkboxes and radio buttons
});
// end clear textbox errors
});
Alright, I was wrong about what the problem was. It's related to the line I thought it was, but it's actually having an issue finding the .error after I wrap the inputs.
Here's where the problem lies:
var errorCheck = $(this).parent("form").children(".error").length > 0;`\
var errorCheck = $(this).parent("form").children(".error").length > 0;
When you .wrap the text inputs, they are no longer children of the form. Use .find
By the way, $(this + "selector") is not valid. You probably want to use $(this).is("selector")
You will need some sort of reference maintained with the new DOM element. This would be placing it as an initialised DOM element in a variable first (not as a string as you did) and the same for the original element, which will be placed back in to maintain the event:
var $inputWrapper = $("<div class=\"inputWrapper\" />"),
$inputText = $("input[type=text]");
$inputText.wrap("<div class=\"inputWrapper\" />");
Then you can replace the element back in.
Related
I'd like to enable/disable buttons on key up change conditionally based on a custom data attribute that matches between an input and a button. I've solved it with just one input, but it seems that when I add another one in the mix, the buttons don't seem to enable.
Furthermore, I have a hunch that it's because of .each() but I can't put my finger on it.
Here's the CodePen I've tried and failed on
var validation = $('[data-validation]');
var validate;
validation.on("change keyup", function (e) {
let validated = true;
validation.each(function () {
let value = this.value;
validate = $(this).data('validation');
if (value && value.trim() != "") {
validated = false;
} else {
validated = true;
return false;
}
});
if (validated) {
$('[data-validator=' + validate + ']').prop("disabled", true);
} else {
$('[data-validator=' + validate + ']').prop("disabled", false);
}
});
The key here is to only run your validation code for the input that was changed. As opposed to what you have, which is to run for all inputs.
To get the input that actually changed, you can utilize the .target property of the event object passed to the event handler.
Alternatively, if you remove the validation.each() entirely, it also works. That is because jQuery sets the value of this to be the DOM element (not a jQuery-wrapped element) that actually triggered the event.
var validation = $("[data-validation]");
var validate;
validation.on("change keyup", function (e) {
let validated = true;
let value = this.value;
validate = $(this).data("validation");
if (value && value.trim() != "") {
validated = false;
} else {
validated = true;
return false;
}
if (validated) {
$("[data-validator=" + validate + "]").prop("disabled", true);
} else {
$("[data-validator=" + validate + "]").prop("disabled", false);
}
});
I've got a table with a button inside a td, once I press the button it adds text to the td. I want to remove this text inside the td once i press the button again. note that this button is used multiple times in the table hence the class attribute.
Which method could I use to get this done?
This is my code:
$(document).on('click', '.releasebutton', function () { // button class="releasebutton"
var label = $(this).text();
if (label == "Add") { // it is "Add" by default
$(this).text("Cancel");
$('.ReleaseTD').append("<br>" + "test"); // td class="ReleaseTD"
}
// the code above this works
else {
$(this).text("Add");
$('.ReleaseTD').remove("<br>" + "test");
// this obviously is wrong but this is where i would like the correct code
};
});
You could create ID for text inside like this:
$(document).on('click', '.releasebutton', function () { // button class="releasebutton"
var label = $(this).text();
if (label == "Add") { // it is "Add" by default
$(this).text("Cancel");
$('.ReleaseTD').append("<span id='textID'><br>" + "test</span>");
}
else {
$(this).text("Add");
$('#textID').remove();
};
});
Please try the following:
$(document).on('click', '.releasebutton', function () { // button class="releasebutton"
var label = $(this).text();
if (label == "Add") { // it is "Add" by default
$(this).text("Cancel");
$('.ReleaseTD').append("<span id='txt_name'><br>" + "test</span>");
}
// the code above this works
else {
$(this).text("Add");
$('#txt_name').remove();
};
});
Two ways:
1) Append your text into a span with a unique ID, and then delete this ID. For example, delete the ID with the largest number. Dumbest way would be to just store the latest ID in a global variable.
var global_last_appended_id = 0;
$(document).on('click', '.releasebutton', function () { // button class="releasebutton"
global_last_appended_id ++;
$('.ReleaseTD').append("<span id='appended-text-" + global_last_appended_id + "'><br>" + "test</span>");
}
// the code above this works
else {
$(this).text("Add");
$('#appended-text-' + global_last_appended_id).remove();
global_last_appended_id--; //go one step back so next time we remove the previous paragraph
};
});
Update: after your edit I've added the ability to undo multiple times. Basically there is unlimited undo.
2) [lame and wrong] Save the previous .html() - the whole HTML code of your element - into a global variable; then restore the previous version of the text from the global variable when necessary.
I am using a plugin called pStrength.jquery.js and for some reason its not submitting the form I have, or it is submitting the form even if it is not supposed to (when I changed the code)
The code i am using is:
$(document).ready(function () {
$('#myForm').submit(function () {
return false;
});
$('#myElement1, #myElement2').pStrength({
'changeBackground': false,
'onPasswordStrengthChanged': function (passwordStrength, strengthPercentage) {
if ($(this).val()) {
$.fn.pStrength('changeBackground', this, passwordStrength);
} else {
$.fn.pStrength('resetStyle', this);
}
$('#' + $(this).data('display')).html('Your password strength is ' + strengthPercentage + '%');
},
'onValidatePassword': function (strengthPercentage) {
$('#' + $(this).data('display')).html(
$('#' + $(this).data('display')).html() + ' Great, now you can continue to change your password!');
$('#myForm').submit(function () {
return true;
});
}
});
});
Someone has told me that I should use booleans and inside the validation checks, set it to true or false.
The problem is that i have no idea how to do this
Is there anyone that could help me and show me the code to do this?
Thank you in advance
The reason it was still submitting was because the onValidatePassword function runs on each individual field, whereas you actually had two fields to validate. If one field validates and the other doesn't, the form would still submit because the Boolean had already been set to true, which was the only condition needed to submit.
Updated code below, you can also refer to the fiddle.
$(document).ready(function () {
$('#myForm').submit(function (event) {
// TODO: check that the two field values match as well
if ($('#myElement1').data('valid') === 'yup' &&
$('#myElement2').data('valid') === 'yup') {
// remove these three lines to make it submit
alert('Submitting...');
event.preventDefault();
return false;
// and uncomment this one line
//return true;
} else {
event.preventDefault();
return false;
}
});
$('#myElement1, #myElement2').data('valid', 'nope');
...
Your complete onValidatePassword callback should now look like this:
'onValidatePassword': function (strengthPercentage) {
$('#' + $(this).data('display')).html(
$('#' + $(this).data('display')).html() + ' Great, now you can continue to change your password!');
formValid = strengthPercentage >= 60;
// set for each element
if (strengthPercentage >= 60) {
$(this).data('valid', 'yup');
} else {
$(this).data('valid', 'nope');
}
}
Inside your onValidatePassword, you're binding to the submit event, instead of submitting the form. Replace this code:
$('#myForm').submit(function () {
return true;
});
with
$('#myForm').submit();
I am trying to do required validation in a asp.net page.
I have multiple controls that will be hidden and displayed.
Controls like checkboxlist,dropdownlist,multiselectedlistbox.
I am using a css class called required attaching to all these controls to check the validation.
I am trying to check if each control has value or not but my code is checking each options with in each controls.
I am really not finding a way not a jquery expert just a novice...
Here is my code any ideas anyone please....
$("input[type='submit']").click(function () {
if ($(this).val() != 'Back') {
var names = [];
var info=" ";
$('.required input').each(function () {
var control = $(this);
if (control.is(':enabled')) {
names[$(this).attr('name')] = true;
}
});
$('.required option').each(function () {
var control = $(this);
if (control.is(':enabled')) {
names[$(this).attr('name')] = true;
}
});
for (name in names) {
var radio_buttons = $("input[name='" + name + "']");
if ((radio_buttons.filter(':checked').length == 0) ||(radio_buttons.filter(':selected').length == 0)) {
info += radio_buttons.closest("table").find('label').html()+"</br>";
}
}
if (info != " ") {
$("#validation_dialog p").html(info);
$("#validation_dialog").dialog({
title: "Validation Error!",
modal: true,
resizable: false,
buttons: {
Close: function () {
$(this).dialog('close');
}
}
});
return false;
}
}
});
here is a fiddle for it...
http://jsfiddle.net/bDmgk/35/
I think what you want is:
$(".required input[type='radio']:checked").each(function(){
});
instead of :
$(".required option").each(function(){ ... });
Hi I made some changes to your fiddle basically I checked for the inputs inside each column like this and then I added them to your names array.
Using
$('table.required:eq(0) input:checked')
I you can got all the inputs that are checked on the first column if the lenght of the array returned is 0 then no input is checked, i't the same procedure for the other ones.
An yes those input names are weird.
Check this fiddle
JSFiddle
What I have is in my fiddle here http://jsfiddle.net/mPuj9/4/
What I tried to do is to disable the button until all of textboxes are filled and the checkbox is checked. My current code is not good, it let you submit in some cases and I don't know how to work it with the checkbox.
CODE
$(document).ready(function() {
$('.textfield').blur(function() {
if ($.trim(this.value) == "") {
$('#btnUpdate').attr("disabled", true);
}
else {
$('#btnUpdate').removeAttr("disabled");
}
});
});
$(document).ready(function() {
$('#termid').change(function() {
var val = $(this).val();
$('#reservationdetails').empty().addClass('loading').load('../kratisis/forms/' + val + '.php', function() {
$('#reservationdetails').removeClass('loading')
});
});
});
Here you go
http://jsfiddle.net/mPuj9/8/
$(document).ready(function () {
$('form').delegate('input:text, input:checkbox', 'blur keyup change', function () {
if(($('form input:text').filter(function(){ return $.trim(this.value) == ''; }).length > 0)
|| ($('form input:checked').length == 0)){
$('#btnUpdate').attr("disabled", true);
}
else {
$('#btnUpdate').removeAttr("disabled");
}
});
});
Here's another way you could do this, which also works if someone presses enter in a text box, or if the browser autofilled an input:
$(function() {
$("form button").attr("disabled", true); //disable buttons at first
var inputs = 0; //keep count of the inputs
$("form input, form select, form textarea").each(function() {
inputs++; //increment counter
$(this).keypress(function() {
if ($.trim($(this).val()) != "") { //if the value isnt empty
inputs--; //decrement counter
if (inputs == 0) { //if theyre all filled in
$("form button").attr("disabled", false);
}
}
}).trigger("keypress"); //in case it was autofilled by the browser
});
$("form").submit(function(e) { //prevent the form being submitted by pressing enter
if (inputs != 0) { //if they arent all filled in
alert("Some fields aren't filled in. Please fix them and try again."); //tell the user
e.preventDefault(); //cancel sending the form
return false;
}
});
});
I think the problem is that you're not using .each() for the text fields. You're checking the one that was recently changed to see if it's value is "", but you're not checking each one.