adjusting default value script to work with multiple rows - javascript

I am using a default value script (jquery.defaultvalue.js) to add default text to various input fields on a form:
<script type='text/javascript'>
jQuery(function($) {
$("#name, #email, #organisation, #position").defaultvalue("Name", "Email", "Organisation", "Position");
});
</script>
The form looks like this:
<form method="post" name="booking" action="bookingengine.php">
<p><input type="text" name="name[]" id="name">
<input type="text" name="email[]" id="email">
<input type="text" name="organisation[]" id="organisation">
<input type="text" name="position[]" id="position">
<span class="remove">Remove</span></p>
<p><span class="add">Add person</span><br /><br /><input type="submit" name="submit" id="submit" value="Submit" class="submit-button" /></p>
</form>
I am also using a script so that users can dynamically add (clone) rows to the form:
<script>
$(document).ready(function() {
$(".add").click(function() {
var x = $("form > p:first-child").clone(true).insertBefore("form > p:last-child");
x.find('input').each(function() { this.value = ''; });
return false;
});
$(".remove").click(function() {
$(this).parent().remove();
});
});
</script>
So, when the page loads there is one row with the default values. The user would then start adding information to the inputs. I am wondering if there is a way of having the default values show up in subsequent rows that are added as well.
You can see the form in action here.
Thanks,
Nick

Just call .defaultValue this once the new row is created. The below assumes the format of the columns is precticable/remains the same.
$(".add").click(function() {
var x = $("form > p:first-child");
x.clone(true).insertBefore("form > p:last-child");
x.find('input:not(:submit)').defaultvalue("Name", "Email", "Organisation", "Position");
return false;
});
You should remove ids from the input fields because once these are cloned, the ids, classes, everything about the elements are cloned. So you'll basically end up with multiple elements in the DOM with the same id -- not good.
A better "set defaults"
Personally I would remove the "set defaults plugin" if it's used purely on the site for this purpose. It can easily be re-created with the below and this is more efficient because it doesn't care about ordering of input elements.
var defaults = {
'name[]': 'Name',
'email[]': 'Email',
'organisation[]': 'Organisation',
'position[]': 'Position'
};
var setDefaults = function(inputElements)
{
$(inputElements).each(function() {
var d = defaults[this.name];
if (d && d.length)
{
this.value = d;
$(this).data('isDefault', true);
}
});
};
Then you can simply do (once page is loaded):
setDefaults(jQuery('form[name=booking] input'));
And once a row is added:
$(".add").click(function() {
var x = $("form > p:first-child");
x.clone(true).insertBefore("form > p:last-child");
setDefaults(x.find('input')); // <-- let the magic begin
return false;
});
For the toggling of default values you can simply delegate events and with the help of setDefault
// Toggles
$('form[name=booking]').delegate('input', {
'focus': function() {
if ($(this).data('isDefault'))
$(this).val('').removeData('isDefault');
},
'blur': function() {
if (!this.value.length) setDefaults(this);
}
});
Fiddle: http://jsfiddle.net/garreh/zEmhS/3/ (shows correct toggling of default values)

Okey, first of all; ids must be unique so change your ids to classes if you intend to have more then one of them.
and then in your add function before your "return false":
var
inputs = x.getElementsByTagName('input'),
defaults = ["Name", "Email", "Organisation", "Position"];
for(var i in inputs){
if(typeof inputs[i] == 'object'){
$(inputs[i]).defaultvalue(defaults[i]);
}
}

Related

How get the Count of Empty Input fields?

How can I check the Number of Incomplete Input fields in Particular ID, (form1, form2).
If 2 input fields are empty, in i want a msg saying something like "Incomplete Input 2"
How is it Possible to do this in JS ?
<div id="form1">
<span>Number of Incomplete Input: 2</span>
<input type="text" value="">
<input type="text" value="">
</div>
<div id="form2">
<span>Number of Incomplete Input: 1</span>
<input type="text" value="Test">
<input type="text" value="">
</div>
This is the JS, which is working, i have have multiple JS with class named assigned to each inputs and get the value, but i need to make this check all the Input fields inside just the ID.
$(document).on("click", "#form1", function() {
var count = $('input').filter(function(input){
return $(this).val() == "";
}).length;
alert(count);
});
Your html structure, especially form structure is not correct, so you should first add some submit button to form that can be clicked. Then you can add event listener on form's submission. In the event handler you should select children inputs inside the form tag using $(this).children("input"). Now you can filter them.
$(document).on("submit", "#form1", function (e) {
e.preventDefault();
var count = $(this)
.children("input")
.filter(function (input) {
return $(this).val() == "";
}).length;
alert(count);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form id="form1">
<span>Number of Incomplete Input: 2</span>
<input type="text" value="">
<input type="text" value="">
<button type="submit">Submit</button>
</form>
This is the JS, which is working, if I have have multiple JS with class named assigned to each inputs and Im getting the value, but i have multiple JS for this to work.
How can i make this Simpler say like, when user clicks on Div, it only checks the input fields inside that div.
$(document).on("click", "#form1", function() {
var count = $('.input_field1').filter(function(input){
return $(this).val() == "";
}).length;
alert(count);
});
HTML
<div id="form1">
<span>Number of Incomplete Input: 2</span>
<input type="text" value="" class="input_field1">
<input type="text" value=""class="input_field1">
</div>
<div id="form2">
<span>Number of Incomplete Input: 1</span>
<input type="text" value="Test" class="input_field2">
<input type="text" value="" class="input_field2">
</div>
See snippet below:
It has commented and if you put some effort on it, you can have a jQuery plugin out of it.
(function () {
'use strict';
var
// this use to prevent event conflict
namespace = 'customValidation',
submitResult = true;
var
input,
inputType,
inputParent,
inputNamePlaceholder,
//-----
writableInputTypes = ['text', 'password'],
checkboxInputType = 'checkbox';
var
errorContainerCls = 'error-container';
// Add this function in global scope
// Change form status with this function
function changeFormStatus(status) {
submitResult = submitResult && status;
}
// Check if a radio input in a
// group is checked
function isRadioChecked(form, name) {
if(!form || !name) return true;
var radio = $(form).find('input[type="radio"][name="' + name.toString() + '"]:checked');
return typeof radio !== 'undefined' && radio.length
? true
: false;
}
function eachInputCall(inp, isInSubmit) {
input = $(inp);
inputType = input.attr('type');
// assume that we have a name placeholder in
// attributes named data-name-placeholder
inputNamePlaceholder = input.attr('data-name-placeholder');
// if it is not present,
// we should have backup placeholder
inputNamePlaceholder = inputNamePlaceholder ? inputNamePlaceholder : 'input';
if(!inputType) return;
// you have three type of inputs in simple form
// that you can make realtime validation for them
// 1. writable inputs ✓
// 2. checkbox inputs ✓
// 3. radio inputs ✕
// for item 3 you should write
// another `else if` condition
// but you should have it for
// each name (it was easier if it was a plugin)
// radio inputs is not good for realtime
// unchecked validation.
// You can check radios through submit event
// let make it lowercase
inputType = inputType.toLowerCase();
// first check type of input
if ($.inArray(inputType, writableInputTypes) !== -1) {
if(!isInSubmit) {
input.on('input.' + namespace, function () {
writableInputChange(this);
});
} else {
writableInputChange(inp);
}
} else if ('checkbox' == inputType) { // if it is checkbox
if(!isInSubmit) {
input.on('change.' + namespace, function () {
checkboxInputChange(this);
});
} else {
checkboxInputChange(inp);
}
}
}
// Check if an input has some validation
// (here we have just required or not empty)
function writableInputChange(inp) {
// I use $(this) instead of input
// to prevent conflict if selector
// is a class for an input
if('' == $.trim($(inp).val())) {
changeFormStatus(false);
// your appropriate message
// you can use bootstrap's popover
// to modefy just input element
// and make your html structure
// more flexible
// or
// if your inputs are in
// separate containers do
// somthing like below
inputParent = $(inp).parent();
if(!inputParent.children('.' + errorContainerCls).length) {
inputParent.append($('<div class="' + errorContainerCls + '" />').text('Please fill ' + inputNamePlaceholder));
}
} else {
changeFormStatus(true);
// I assume we have separate
// containers for each input
inputParent = $(inp).parent();
inputParent.children('.' + errorContainerCls).remove();
}
}
// Check if an checkbox is checked
function checkboxInputChange(chk) {
if(!$(chk).is(':checked')) {
changeFormStatus(false);
// if your inputs are in
// separate containers do
// somthing like below
inputParent = $(chk).parent();
if(!inputParent.children('.' + errorContainerCls).length) {
inputParent.append($('<div class="' + errorContainerCls + '" />').text('Please check ' + inputNamePlaceholder));
}
} else {
changeFormStatus(true);
// I assume we have separate
// containers for each input
inputParent = $(chk).parent();
inputParent.children('.' + errorContainerCls).remove();
}
}
$(function () {
var
form = $('#form'),
// you can change this selector with your classes
formInputs = form.find('> .input-group > input');
formInputs.each(function () {
eachInputCall(this);
});
form.submit(function () {
submitResult = true;
// check all inputs after form submission
formInputs.each(function () {
eachInputCall(this, true);
});
// Because of radio grouping by name,
// we should select them separately
var selectedGender = isRadioChecked($(this), 'gender');
var parent;
if(selectedGender) {
changeFormStatus(true);
parent = $(this).find('input[type="radio"][name="gender"]').parent();
parent.children('.' + errorContainerCls).remove();
} else {
changeFormStatus(false);
// I assume that all radios are in
// a separate container
parent = $(this).find('input[type="radio"][name="gender"]').parent();
if(!parent.children('.' + errorContainerCls).length) {
parent.append($('<div class="' + errorContainerCls + '" />').text('Please check your gender'));
}
}
if(!submitResult) {
console.log('There are errors during validations!');
}
return submitResult;
});
});
})(jQuery);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form id="form">
<div class="input-group">
<input type="text" name="input1" data-name-placeholder="name">
</div>
<div class="input-group">
<input type="checkbox" name="input2" data-name-placeholder="agreement">
</div>
<div class="input-group">
<input type="radio" name="gender">
<input type="radio" name="gender">
</div>
<button type="submit">
submit
</button>
</form>

How to pass dynamic value to jquery validation function

I have a form which have some dynamically added input,
Here i input have total_amt = 100;
How can i, form should not submit until, sum of all the dynamically added inputs must be equal to total_amt
Here is my code.
$(function(){
var i = 1;
$('#add_more').click(function(event) {
event.preventDefault();
$('input.items').last().attr('name', 'item['+i+']');
$('#cart_items').append($('#tmp_cart').html());
$('input[name="item['+i+']"]').rules("add", {
required: true,
depositsSum : function(){
return $(this).val();
},
messages:'Sum of total items should be equal to 100',
});
i++;
});
$.validator.addMethod("depositsSum", function(value, element, params)
{
var amnts = 0;
$(params[0]).each(function() {
amnts += parseFloat($(this).val());
});
return amnts;
});
$("#myForm").validate({
rules: {
'item[0]': {
required:true
}
}
});
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.17.0/jquery.validate.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.17.0/additional-methods.min.js"></script>
<form action="" method="POST" id="myForm">
Total Items<input type="text" value="100" name="total_amt" id="total_amt">
<div id="cart_items">
Items<input type="text" name="item[0]" class="items"><br/>
</div>
<button id="add_more">Add More</button>
<input type="submit" name="submit" value="submit">
</form>
<div id="tmp_cart" style="display: none;">
<label>
Items<input type="text" name="item[]" class="items">
</label><br/>
</div>
Two flaws in your code...
Within your .rules() method:
depositsSum : function(){
return $(this).val();
},
You're trying to set the parameter of you custom rule to the value of the field. This is complete nonsense. A parameter is something like Max: 10, where 10 is the parameter and it defines the rule; it's never the actual value of the field, which, by the way, always changes and is empty when the page loads. When you want to invoke the custom rule, set the parameter to true.
And related to the next problem...
Within your .addMethod() method:
$(params[0]).each(function() {
amnts += parseFloat($(this).val());
});
The params argument would be useless in your case, since the parameter can not be used for passing the dynamic values of other fields. Use a jQuery selector to grab the other fields. Since the name begins with item, use the "starts with" selector.
$('[name^="item"]').each(function() {
amnts += parseFloat($(this).val());
});

Multiple inputs with duplicate value check

I have a button to create input tags. When user click submit button I want to find inputs with duplicate values and change border to red.
I'm not using jquery validate plugin
html code:
<form>
<table>
<tr>
<td><input type="text" name="text[]" id="1"> <button class="add">add</button></td>
</tr>
</table>
<input type="submit" id="submit" value="check">
</form>
jQuery code:
// add input
var i = 2;
$('.add').click(function(e){
e.preventDefault();
$('table').append("<tr><td><input type="text" name="text[]" id="'+i+'"> <button class="add"></td></tr>");
i++;
});
$('#submit').click(function(){
// I do not know how to write ...
});
Here is what you want
$('#submit').click(function () {
var valid = true;
$.each($('input[type="text"]'), function (index1, item1) {
$.each($('input[type="text"]').not(this), function (index2, item2) {
if ($(item1).val() == $(item2).val()) {
$(item1).css("border-color", "red");
valid = false;
}
});
});
return valid;
});
If somebody is after this, with a lot of inputs, and is concerned with efficiency, this yields the same result (duplicates besides the first occurrence are marked):
$('#submit').click(function(){
var values = []; //list of different values
$('table input:text').each(
function() {
if (values.indexOf(this.value) >= 0) { //if this value is already in the list, marks
$(this).css("border-color", "red");
} else {
$(this).css("border-color", ""); //clears since last check
values.push(this.value); //insert new value in the list
}
}
);
});
fiddle:
https://jsfiddle.net/4s82L4vg/

enable buttons in javascript/jquery based on regex match

I'm having trouble getting the match to bind to the oninput property of my text input. Basically I want my submit button to be enabled only when the regular expression is matched. If the regex isn't matched, a message should be displayed when the cursor is over the submit button. As it stands, typing abc doesn't enable the submit button as I want it to. Can anyone tell me what I'm doing wrong? Thank you.
<div id="message">
</div>
<form method="POST">
<input type="text" id="txt" oninput="match()" />
<input type="submit" id="enter" value="enter" disabled />
</form>
<script>
var txt = $("#txt").value();
var PATTERN = /abc/;
var REQUIREMENTS = "valid entries must contain the string 'abc'";
// disable buttons with custom jquery function
jQuery.fn.extend({
disable: function(state) {
return this.each(function() {
this.disabled = state;
});
}
});
$('input[type="submit"]).disable(true);
var match = function(){
if (txt.match(PATTERN)){
$("#enter").disable(false)
}
else if ($("#enter").hover()){
function(){
$("#message").text(REQUIREMENTS);
}
}
</script>
Your code would be rewrite using plain/vanille JavaScript.
So your code is more clean and better performance:
<div id="message"></div>
<form method="POST">
<input type="text" id="txt" oninput="match()" />
<input type="submit" id="enter" value="enter" disabled />
</form>
<script>
var txt;
var enter = document.getElementById('enter');
var message = document.getElementById('message');
var PATTERN = /abc/;
var REQUIREMENTS = "valid entries must contain the string 'abc'";
function match() {
txt = document.getElementById('txt').value;
if (PATTERN.test(txt)) {
enter.disabled = false;
} else if (isHover(enter)) {
enter.disabled = true;
message.innerHTML = REQUIREMENTS;
} else {
enter.disabled = true;
}
}
function isHover(e) {
return (e.parentElement.querySelector(':hover') === e);
}
</script>
If you wanted to say that you want handle the events in different moments, your code should be the following.
Note: the buttons when are disabled doesn't fired events so, the solution is wrapper in a div element which fired the events. Your code JavaScript is more simple, although the code HTML is a bit more dirty.
<form method="POST">
<input type="text" id="txt" oninput="match()" />
<div style="display: inline-block; position: relative">
<input type="submit" id="enter" value="enter" disabled />
<div id="buttonMouseCatcher" onmouseover="showText(true)" onmouseout="showText(false)" style="position:absolute; z-index: 1;
top: 0px; bottom: 0px; left: 0px; right: 0px;">
</div>
</div>
<script>
var txt;
var enter = document.getElementById('enter');
var message = document.getElementById('message');
var PATTERN = /abc/;
var REQUIREMENTS = "valid entries must contain the string 'abc'";
function match() {
txt = document.getElementById('txt').value;
if (PATTERN.test(txt)) {
enter.disabled = '';
} else {
enter.disabled = true;
}
}
function showText(option) {
message.innerHTML = option ? REQUIREMENTS : "";
}
</script>
Two problems here:
The variable txt is defined once outside the function match, so the value is fixed to whatever the input with id txt has when the script/page is loaded.
You should move var txt = $("#txt").val(); into the match function.
Notice I changed the function value() to val().
Problems identified:
jQuery events don't happen on disabled inputs: see Event on a disabled input
I can't fix jQuery, but I can simulate a disabled button without it actually being disabled. There's other hacks you could do to get around this as well, for example, by overlaying a transparent element which actually captures the hover event while the button is disabled.
Various syntactical errors: format your code and read the console messages
.hover()){ function() { ... } } is invalid. It should be .hover(function() { ... })
else doesn't need to be followed by an if if there's no condition
.hover( handlerIn, handlerOut ) actually takes 2 arguments, each of type Function
$('input[type="submit"]) is missing a close '
Problems identified by #Will
The jQuery function to get the value of selected input elements is val()
val() should be called each time since you want the latest updated value, not the value when the page first loaded
Design issues
You don't revalidate once you enable input. If I enter "abc" and then delete the "c", the submit button stays enabled
You never hide the help message after you're done hovering. It just stays there since you set the text but never remove it.
https://jsfiddle.net/Lh4r1qhv/12/
<div id="message" style="visibility: hidden;">valid entries must contain the string 'abc'</div>
<form method="POST">
<input type="text" id="txt" />
<input type="submit" id="enter" value="enter" style="color: grey;" />
</form>
<script>
var PATTERN = /abc/;
$("#enter").hover(
function() {
$("#message").css('visibility', $("#txt").val().match(PATTERN) ? 'hidden' : 'visible');
},
$.prototype.css.bind($("#message"), 'visibility', 'hidden')
);
$('form').submit(function() {
return !!$("#txt").val().match(PATTERN);
});
$('#txt').on('input', function() {
$("#enter").css('color', $("#txt").val().match(PATTERN) ? 'black' : 'grey');
});
</script>

Build and manipulate array based on required fields populated

I'm trying to figure out a sensible way to display and manipulate an array/list of required fields which are yet to be populated in a form - this is just so i can output this info to the user and remove each item from the list as the user goes through and populates the fields (as a sort of progress indicator). Any thoughts on how best to handle this?
I'm thinking of something along the lines of the following:
var reqFields = [];
jQuery('label.required').each(function() {
console.log(jQuery(this).text());
reqFields.push(jQuery(this).text());
});
jQuery('.custom-field').on('input', function() {
if (jQuery('.required-entry').filter(function() {
return this.value.length === 0;
}).length === 0) {
// Remove this from the list/array
} else {
}
});
On input event check the value and accordingly add/remove item in array.
var reqFields = [];
jQuery('label.required').each(function() {
console.log(jQuery(this).text());
reqFields.push(jQuery(this).text());
});
jQuery('.custom-field').on('input', function() {
if (this.value) {
// Remove this from the list/array
reqFields.splice(jQuery(this).index(),1);
// jQuery(this).index() havent tried, else just compute index some other way
} else {
// add back if cleared out
reqFields.push( jQuery('label.required').eq(jQuery(this).index()).text());
}
});
Instead of removing the entries, every time there's a change in input of the required fields, you can simply re-assign the reqFields array to the list of required fields with empty input.
var reqFields = [];
jQuery(function() {
jQuery('.requiredFields').on('input', function() {
reqFields = jQuery('.requiredFields').filter(function() {
return this.value.length === 0;
});
});
});
Check this basic example bellow using each on input to loop through all the fields with class required-entry and check the empty ones to finally append message to span #msg to inform the user which fields are required.
Hope this helps.
$('.required-entry').on('input', function() {
$('#msg').empty();
$('.required-entry').each(function() {
if ( $(this).val().length == 0 )
$('#msg').append('Field <b>'+$(this).prev('label').text()+'</b> is required.<br/>');
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label class='required'>First Name</label>
<input type='text' id='first_name' name='first_name' class='required-entry' required/>
<br/>
<label class='required'>Last Name</label>
<input type='text' id='last_name' name='last_name' class='required-entry' required/>
<br/>
<label class='required'>Email Address</label>
<input type='text' id='email' name='email' class='required-entry' required/>
<hr/>
<br/>
<span id='msg'></span>

Categories

Resources