Dynamically added fields not working with calendar field - javascript

I am trying to attach a calendar field to a dynamically added html code.
Initially, the code shows 3 input fields (as shown in the "p_scents" div).
When the "Add Another Employer" is clicked, it should generate another 3 inputs( as the ones above).
It is working fine for me to generate the first 2 fields (without the calendar field), but when I add the calendar field, it is not working.
<body>
<h2>Add Another Employer</h2>
<div id="p_scents">
<p>
<label>Employer Name</label><input class="dynamic" type="text" name="employern" id="employern" />
<label>Job Title</label><input class="dynamic" type="text" name="jtitle" id="jtitle" />
<label>Start Date </label>
<input type="text" name="startd" class="textfield" />
<script language="JavaScript">
new tcal ({
// form name
'formname': 'form',
// input name
'controlname': 'startd'
});
</script>
</p>
</div>
<script type="text/javascript">
$(function() {
var scntDiv = $('#p_scents');
var i = $('#p_scents p').size() + 1;
$('#addScnt').live('click', function() {
if( i <= 10 ) {
$('<p><label>Employer Name</label><input class="dynamic" type="text" name="employern' + i +'" id="employern" /><label>Job Title</label><input class="dynamic" type="text" name="jtitle' + i +'" id="jtitle" /><label>Start Date </label>
<input type="text" name="startd' + i +'" class="textfield" />
<script language="JavaScript">
new tcal ({'formname': 'form','controlname': 'startd' + i +''});</script>Remove</p>').appendTo(scntDiv);
i++;
return false;}
else{
alert('Maximum Reached!');
}
});
$('#remScnt').live('click', function() {
if( i > 2 ) {
$(this).parents('p').remove();
i--;
}
return false;
});
});
</script>
</body>

Sorry, but there is lot of stuff wrong/not good in your code. I'm trying to give some suggestions how to improve this, but first, what's wrong:
IDs have to be unique. In your code, you give multiple elements the same ID. Especially the remove link will not work.
Strings cannot span multiple lines in JavaScript.
Don't add such a bunch of HTML as string. You have a quotation error in this string.
Don't add <script> tags this way (at least here it is not necessary).
My suggestions:
Remove the script tag from the HTML, you don't need it and remove the IDs of the input elements
<h2>Add Another Employer</h2>
<div id="p_scents">
<p>
<label>Employer Name</label><input class="dynamic" type="text" name="employern" />
<label>Job Title</label><input class="dynamic" type="text" name="jtitle" />
<label>Start Date </label>
<input type="text" name="startd" class="textfield" />
</p>
</div>
You also don't need to use live [docs] for the click event handler on #addScnt. Just use click [docs]:
$('#addScnt').click(...
You only need live for elements you add dynamically.
Now the most important thing: How you add new fields.
You can do this very easily, by cloning the existing p element. The only thing you have to remember is to change the name of input fields (add the i) and call the tcal function:
$('#addScnt').click(function() {
if (i <= 10) {
$('#p_scents p:first').clone() // clone
.find('input').attr('name', function(index, value) { // change name
return value + i;
}).end()
.append('Remove') // add remove link
.appendTo(scntDiv);
// init calender
new tcal({
formname: 'form',
controlname: 'startd'+i
});
i++;
return false;
}
else {
alert('Maximum Reached!');
}
});
Reference: clone [docs], attr [docs]
Note that the remove link has a class, not an id. For this link it is better to use delegate [docs]:
$('#p_scents').delegate('.remScnt', 'click', function() {
if (i > 2) {
$(this).closest('p').remove();
i--;
}
return false;
});
Also note that I use closest [docs] here, which only gives the closest p element. If you use parents, you will remove all ancestor p elements and that might result in removing a lot more than you intended.
Last but not least, you also have to make a call to
new tcal ({
// form name
'formname': 'form',
// input name
'controlname': 'startd'
});
because we removed the script tag.
Here is a working demo of all that: http://jsfiddle.net/fkling/ygSn9/ (with empty tcal function).

Related

Two input fields with the same name - on change event

I have 2 input fields with the same name - that is because business logic of the project.
They look like that:
<input type="file" name="director_front_passport[]" class="app-file" id="director_front_passport" />
<input type="file" name="director_front_passport[]" class="app-file" />
I need to append image name after input field on change event.But in this way, how to make difference between these 2 inputs?
I thought to try to differ them by id attr, but I have clone button to add more fields and I don't think this will work on change event.
Updated: My code for on change event is the following:
var inputs = document.querySelectorAll( '.app-file' );
Array.prototype.forEach.call( inputs, function( input )
{
input.addEventListener( 'change', function( e )
{
//my code for displaying image
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
I updated my code using $(this) to find changed input and my code looks:
var inputs = document.querySelectorAll( '.app-file' );
Array.prototype.forEach.call( inputs, function( input )
{
input.addEventListener( 'change', function( e )
{
var changed = $(this);
var label = changed.next(),
labelVal = label.innerHTML,
divName = label.next();
fileName = e.target.value.split('\\').pop();
divName.html(fileName);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input type="file" name="director_front_passport[]" class="app-file" id="director_front_passport" />
<input type="file" name="director_front_passport[]" class="app-file" />
You can use the this keyword within the event handler to identify the element which raised the event. Try this:
$('.app-file').change(function() {
$(this).after('<div>' + this.files[0].name + '</div>');
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="file" name="director_front_passport[]" class="app-file" id="director_front_passport" />
<input type="file" name="director_front_passport[]" class="app-file" />
With your second example it's a little odd to call forEach in the manner you are. You can just call forEach on the nodeList returned from querySelectorAll, like this:
document.querySelectorAll('.app-file').forEach(function(input) {
input.addEventListener('change', function(e) {
// my code for displaying image
})
}

Jquery one button updates multiple input fields on form

I am trying to update two input fields in a form when clicking one button. I actually had all the code right when using document.getElementById, but the form that I'm using strips the ID's I set away, so I can't use getbyid. If I know the form field name, how could I change my function to do the same thing? Please note that my form has more than two fields, including a submit button, so I don't want to update those.
This is what I used before (with the ID selector)
Html:
<input type="text" name="field-1" id="info1">
<input type="text" name="field" id="info2">
Populate
JS:
function addTxt(val, id,no)
{
var id = id;
for(var i=1;i<=no;i++){
document.getElementById(id+i).value = val[i-1];
}
}
Fiddle:
http://jsfiddle.net/qwz47phx/3/
Edited with a much simpler and readable approach
function addVal(obj) {
event.preventDefault(); // Prevent page scrolltop on anchor click
$.each(obj, function(k, v) {
$("input[name='"+ k +"']").val( v );
})
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" name="foo">
<input type="text" name="bar">
<a href="#" onclick='addVal({foo:"Hello", "bar-baz":"World"})'>Populate</a>
Or with native JS (ES5+):
function addVal(obj) {
Object.keys(obj).forEach(function(name) {
document.querySelector('input[name="' + name + '"]').value = obj[name];
});
}
<input type="text" name="foo">
<input type="text" name="bar">
<input type="text" name="name-with-dashes">
<a href="#" onclick='addVal({foo:"Hello", bar:"World", "name-with-dashes": "Works !"})'>Populate</a>
If you have problems with IDs you can use querySelector to select inputs by name like this:
JS:
function addTxt(val, id, no) {
for (var i = 1; i <= no; i++) {
document.querySelector('input[name="' + id + i + '"]').value = val[i - 1];
}
}
HTML:
<input type="text" name="info1" id="info1">
<input type="text" name="info2" id="info2">
Populate
Demo: http://jsfiddle.net/iRbouh/qwz47phx/6/
I hope this will help you.
You can use a jQuery attribute= selector to grab by name instead of ID.
function addTxt(val, id,no)
{
for(var i=1;i<=no;i++){
var name = id+i;
$("input[name='"+name+"']").val(val[i-1]);
}
}
Please note that this function will be looking for names of info1, info2, info3, etc, just as your original script did. However, in the HTML, you have names of info and info-1. Either the names will have to be changed to fit the function, or the function can be slightly more intricate.
Fiddle: http://jsfiddle.net/qwz47phx/8/

How to manipulate individual input field values without a lot of code

I wrote some code using jQuery to convert <input> field values from one unit system to another (English <-> Metric). All was going well until I have realized that I am using a class selector, so instead of each value doing its conversion individually, all values (with same class) get converted to the same identical value (equal to the first occurrence of class).
An obvious solution is to assign an id to each value, which I suppose will work, but I am here to ask if there is a better way. I have a lot of values (which is why I tried using class), and would like to avoid using id, if possible. But, all I am looking for is "convert each value individually (using my conversion function)". How can this be done?
jQuery
function convertValues() {
if ($('#unit_system').val() == "English") //if changed to English
{
$('.value_gpm').val( //do converstion from Metric to English
convert($('.value_gpm').val(), "m3h", "gpm")
);
}
else if ($('#unit_system').val() == "Metric") //if changed to Metric
{
$('.value_gpm').val( //do conversion from English to Metric
convert($('.value_gpm').val(), "gpm", "m3h")
);
}
}
Calling Function
//below code is for select box (HTML for it is not shown)
$("#unit_system").change(function(){ //select box change detected
convertValues(); //function is called
});
HTML at first (before Select box change)
<input type="text" class="value_gpm" name="design_a" value="444" />
<input type="text" class="value_gpm" name="design_b" value="555" />
<input type="text" class="value_gpm" name="design_c" value="666" />
<input type="text" class="value_gpm" name="design_d" value="777" />
<input type="text" class="value_gpm" name="design_e" value="888" />
HTML after (after Select box is changed)
<input type="text" class="value_gpm" name="design_a" value="1954.87" />
<input type="text" class="value_gpm" name="design_b" value="1954.87" />
<input type="text" class="value_gpm" name="design_c" value="1954.87" />
<input type="text" class="value_gpm" name="design_d" value="1954.87" />
<input type="text" class="value_gpm" name="design_e" value="1954.87" />
Expected behavior: conversion produces different value per row
Actual behavior: same value produced for each row
Just loop through them, something like this.
var inputs = $('.value_gpm');
for(i=0;i < inputs.length; i++){
var input = inputs[i];
input.val( convert(input.val(), "m3h", "gpm") );
}
Best bet - using $.each and $(this).
$(document).ready(function(){
var valueEls = $('.value_gpm');
$("#unit_system").change(function(){
var unit = $(this).val();
switch(unit){
case "English":
valueEls.each(function(){
$(this).val(convert($(this).val(), "m3h", "gpm");
});
break;
case "Metric":
valueEls.each(function(){
$(this).val(convert($(this).val(), "gpm", "m3h");
});
break;
}
});
});
Use each()
$("value_gpm").each(function () {
convert(this.val(), ...etc
The less lines of codes I figure out for this is this:
var unit_system = $('#unit_system').val();
$('.value_gpm').each(function(){
convert($(this).val(), unit_system == "English" ? "m3h" : "gpm", unit_system == "English" ? "gpm" : "m3h");
});
You can use jQuery each:
$("#unit_system").change(function(){
var fromUnit = "m3h";
var toUnit = "gpm";
if ($(this).val() == "Metric"){
fromUnit = "gpm";
toUnit = "m3h";
}
$('.value_gpm').each(function(){
$(this).val(convert($(this).val(), fromUnit, toUnit));
});
});

How to reset a particular form field using jQuery

I want to know how to reset a particular form field using jQuery.
I'm using the folowing function:
function resetForm(id) {
$('#'+id).each(function(){
this.reset();
});
}
but it is resetting all the fields. Is there any way to reset specific fields using jQuery or JavaScript? I want to reset only a particular field.
function resetForm(id) {
$('#' + id).val(function() {
return this.defaultValue;
});
}
example without using id:
http://jsfiddle.net/vYWdm/
The reset() method affects the whole form, by design, to reset only particular input elements, assuming that there's a Reset previous inputelement after eachinput`:
$('button.reset').click(
function(){
var input = $(this).prev('input:first');
input.val(''); // assuming you want it reset to an empty state;
});
JS Fiddle demo
To reset the input to its original state, then first I'd recommend storing the original value in a data-* attribute for recollection:
$('input').each(
function(){
$(this).attr('data-originalValue',$(this).val());
});
$('button.reset').click(
function(){
var input = $(this).prev('input:first');
input.val(input.attr('data-originalValue'));
});
JS Fiddle demo
Given HTML similar to the following (in which the input elements are grouped together):
<form action="#" method="post">
<fieldset>
<input value="something" />
<button class="reset">Reset the input</button>
</fieldset>
<fieldset>
<input type="checkbox" name="two" />
<input type="checkbox" name="two" checked />
<input type="checkbox" name="two" />
<button class="reset">Reset the input</button>
</fieldset>
<fieldset>
<input type="radio" name="three" checked />
<input type="radio" name="three" />
<button class="reset">Reset the input</button>
</fieldset>
</form>
The following jQuery will reset the input elements back to their page-load state:
$('button.reset').click(
function () {
$(this).prevAll('input').val(function(){
switch (this.type){
case 'text':
return this.defaultValue;
case 'checkbox':
case 'radio':
this.checked = this.defaultChecked;
}
});
});
JS Fiddle demo.
References:
attr().
prev().
reset()
val().
My approach would be to consider three cases: free-input-based fields, check-based fields and select-based fields.
$(set_of_fields).each(function() {
// Don't bother checking the field type, just check if property exists
// and set it
if (typeof(this.defaultChecked) !== "undefined")
this.checked = this.defaultChecked;
if (typeof(this.defaultValue) !== "undefined")
this.value = this.defaultValue;
// Try to find an option with selected attribute (not property!)
var defaultOption = $(this).find('option[selected]');
// and fallback to the first option
if (defaultOption.length === 0)
defaultOption = $(this).find('option:first');
// if no option was found, then it was not a select
if (defaultOption.length > 0)
this.value = defaultOption.attr('value');
});
Edit: I just noticed this won't work with <select multiple> fields.
You could do (if you plan to use the reset() javascript method):
function resetForm(id) {
document.getElementById(id).reset();
}
There is no need for jQuery as the method "reset" is a standard javascript method

adjusting default value script to work with multiple rows

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]);
}
}

Categories

Resources