I have some code which adds fields but currently it adds an infinite abouts of boxes. How can I constrain it to only be a max of 10. I ideally want it to alert when I try to add more after 10.
http://jsfiddle.net/spadez/9sX6X/13/
var container = $('.copies'),
value_src = $('#current');
$('.copy_form')
.on('click', '.add', function(){
var value = value_src.val();
var html = '<div class="line">' +
'<input class="accepted" type="text" value="' + value + '" />' +
'<input type="button" value="X" class="remove" />' +
'</div>';
$(html).appendTo(container);
value_src.val('');
})
.on('click', '.remove', function(){
$(this).parents('.line').remove();
});
The code I know:
alert("Only 10 allowed");
The code I had a go at:
var i = 0 // Set counter
i++ // Increment counter
if(i > 10) {
alert("Only 10 allowed");
}
else {
// code to be executed
}
This is one of my first scripts and I wondered if I could get help on the right way to implement this because the code I tried above broke my current working code.
Within your click handler, check if the number of elements with the class line is less than 10.
if ($('.line').length < 10) {
//execute code
}else{
alert('Only 10 allowed');
return false;
}
Fiddle
Rather than embedding 'magic numbers' in your code (see: What is a magic number, and why is it bad?), define a maxFields variable and maintain a count throughout, checking against that value each time another one tries to be added.
This allows your code to be more portable and reusable by someone else, or by you for another use case, when say you want 20 fields.
It also reads more like English (current field is less than max fields) which leads to self documentation.
http://jsfiddle.net/9sX6X/21/
var container = $('.copies'),
value_src = $('#current'),
maxFields = 10,
currentFields = 1;
$('.copy_form').on('click', '.add', function () {
if (currentFields < maxFields) {
var value = value_src.val();
var html = '<div class="line">' +
'<input class="accepted" type="text" value="' + value + '" />' +
'<input type="button" value="X" class="remove" />' +
'</div>';
$(html).appendTo(container);
value_src.val('');
currentFields++;
} else {
alert("You tried to add a field when there are already " + maxFields);
}
})
.on('click', '.remove', function () {
$(this).parents('.line').remove();
currentFields--;
});
From Wikipedia:
The term magic number also refers to the bad programming practice of
using numbers directly in source code without explanation. In most
cases this makes programs harder to read, understand, and maintain.
Although most guides make an exception for the numbers zero and one,
it is a good idea to define all other numbers in code as named
constants.
Here I used the .length method from jQuery.
var container = $('.copies'),
value_src = $('#current');
$('.copy_form')
.on('click', '.add', function(){
if ($('.accepted').length < 10)
{
var value = value_src.val();
var html = '<div class="line">' +
'<input class="accepted" type="text" value="' + value + '" />' +
'<input type="button" value="X" class="remove" />' +
'</div>';
$(html).appendTo(container);
value_src.val('');
}
else
{
alert("Only 10 allowed");
}
})
.on('click', '.remove', function(){
$(this).parents('.line').remove();
});
Fiddle
Related
I'm kind of confused on how to dynamically delete each row while also updating all row index accordingly, instead of row 1,2,3, while deleting 2, the rows should be append into 1,2, not remained 1,3..
jQuery(function(){
jQuery('a.add-author').click(function(event){
var number=document.getElementById("noofinputs").value;
event.preventDefault();
number++;
var newRow = jQuery(
'<tr>'+
'<td><textarea class="txtsize" name="item' +number + '" id="item' +number + '" rows="5" cols="32"></textarea></td>'+
'<td><select name="category' +number + '" id="category' +number + '" style="width:202px;" >'+
<?php
$q3=mysqli_query($con,"select * from categories ORDER BY category ASC");
while ($row3 = mysqli_fetch_assoc($q3)){
?>
'<option value="<?php echo $row3['no']; ?>"><?php echo $row3['category']; ?></option>'+
<?php
}
?>
+'</select></td>'+
'<td>$<input type="text" size="10" name="amount' +number + '" id="amount' +number + '" /></td>'+
'<td><img style="cursor: pointer;" height="24px" width="24px;" src="http://../images/Cancel.png" /> </td>'+
'</tr>');
jQuery('table.authors-list').append(newRow);
$('#noofinputs').val(number);
});
});
$(document).ready(function () {
$(".remove-author").click(function () {
removeRow(this);
});
});
function removeRow(elem){
var i = 0;
var ii = 0;
var iii = 0;
$(elem).closest('tr').remove();
$("table.authors-list tr").not(':first').each(function (){
$('td', this).not(':last').each(function() {
$(this).find('textarea').each(function(){
$(this).attr('name', 'item' + ( i+1 ));
i++;
});
$(this).find('select').each(function(){
$(this).attr('name', 'category' + ( ii+1 ));
ii++;
});
$(this).find('input').each(function(){
$(this).attr('name', 'amount' + ( iii+1 ));
iii++;
});
});
});
var a=document.getElementById("noofinputs").value;
var b = (a - 1);
$('#noofinputs').val(b);
}
I edited the code yet I can't even delete a single row...
I tried to follow this renumber appended table row in javascript after deleting
but it's not working at all...
EDITED: FINALLY it can be deleted and renumber its "number" name attribute after some changes!
Edit: Looks like you need to remove the number from <a href="#" title="" class="remove-author'+number+'">. Just leave it as <a href="#" title="" class="remove-author">.
You also you want to remove the $('.remove-author').each(function(){
jQuery doesn't act on elements that are created dynamically. So you'll want to create a new function and inject it into the <a> element (not the best solution, but it will work without heavily modifying your code)
So your code should be
$(document).ready(function () {
$(".remove-author").click(function () {
removeRow(this);
});
});
function removeRow(elem){
$(elem).closest('tr').remove();
$("table.authors-list tr").each(function (i){
var txt = $(this).find('textarea').attr('name');
$(this).find('textarea').attr('name', txt.replace(/\d+/, i+1));
var sel = $(this).find('select').attr('name');
$(this).find('select').attr('name', sel.replace(/\d+/, i+1));
var amt = $(this).find('input').attr('name');
$(this).find('input').attr('name', amt.replace(/\d+/, i+1));
});
}
now you will want to add this to the <a> element
<a href="#" title="" class="remove-author" click="removeRow(this);">
I've created a JSfiddle here:
basically I have a form that will allow users to input additional sections... but when I have added more than 2 units and then proceed to click on the 'plus' (+) icon I get more than 1 element created in that section... its probably something elementary, but any info will help.
Move your Click functions out of the click function
//add unit input box and increment click counter by one.
addUnit.click(function () {
unitCounter += 1;
unitElementCount = jQuery(".unit-element").length;
if (unitCounter <= 4) {
error.hide();
container.append('<table id="unit-' + unitCounter + '-div" class="create-course-table-element unit-element"><tr><td><label class="unit-label">Unit ' + unitCounter + '</label></td><td><input class="create-course-input-element unit-input" id="unit-id-' + unitCounter + '" name="unit-' + unitCounter + '" /><div id="delete-unit-' + unitCounter + '" class="ui-icon ui-icon-circle-close del-unit" title="Delete unit"></div></td></tr><tr><td align="center">Sections</td><td><div id="add-section-icon-' + unitCounter + '" class="ui-icon ui-icon-plus add-section-icon"></div></td></tr></table><div id="section-id-' + unitCounter + '-div" class="this-section"></div>');
} else if (unitElementCount == 4) {
unitCounter = 5;
error.html("");
error.fadeIn(1500);
error.append("<p class='error-message'>Note: You are only able to add 4 units to a given course. Each unit allows you to add 10 separate sections of content; therefore you may add a total of 40 different sections to a given course. If the material requires more units, you should consider dividing the course into 2 parts.</p>");
}
});
//This part has been slightly modified and moved out of the addUnit.click() function
var counterSecTwo = 0;
var counterSecThree = 0;
var counterSecFour = 0;
jQuery(document).on("click", "#add-section-icon-2",function () {
counterSecTwo += 1;
var container = jQuery("#section-id-2-div");
container.append("<p>test "+counterSecTwo+"</p>");
});
jQuery(document).on("click", "#add-section-icon-3",function () {
counterSecThree += 1;
var container = jQuery("#section-id-3-div");
container.append("<p>test "+counterSecThree+"</p>");
});
jQuery(document).on("click", "#add-section-icon-4",function () {
counterSecFour += 1;
var container = jQuery("#section-id-4-div");
container.append("<p>test "+counterSecFour+"</p>");
});
});
Here I am binding the click handlers to Document as the elements do not exist yet: you could also add the event listener when you create the actual element.
Modified fiddle: http://jsfiddle.net/vewP7/
I have some code which uses this to allow to keep the same function code but apply it to different form elements which can be seen on a jsFiddle demo
//latest
var maxFields = 10,
currentFields = 1;
$('.form').on('click', '.add', function () {
var value_src = $(this).prev();
var container = $(this).parent().prev();
if ($.trim(value_src.val()) != '') {
if (currentFields < maxFields) {
var value = value_src.val();
var html = '<div class="line">' +
'<input id="accepted" type="text" value="' + value + '" />' +
'<input type="button" value="X" class="remove" />' +
'</div>';
$(html).appendTo(container);
value_src.val('');
currentFields++;
} else {
alert("You tried to add a field when there are already " + maxFields);
}
} else {
alert("You didn't enter anything");
}
})
.on('click', '.remove', function () {
$(this).parents('.line').remove();
currentFields--;
});
My issue is that I still want to be able to limit each section to only have 10 <inputs>, but at the moment each section shares the counter, so 5 in requirements and 5 in qualifications would trigger the 10 limit.
Is there a nice clean way of keeping the input field counter separate for each section?
What you need to do is store the current number of children for each list in a context sensitive way. There are a couple ways you could structure this (it would be easy using MVC libraries or the likes), but the simplest solution for your code will be to just use the DOM. So instead of using your global currentFields variable, instead use container.children().length to get the number of notes in the list you are currently operating on.
http://jsfiddle.net/9sX6X/70/
//latest
var maxFields = 10;
$('.form').on('click', '.add', function () {
var value_src = $(this).prev();
var container = $(this).parent().prev();
if ($.trim(value_src.val()) != '') {
if (container.children().length < maxFields) {
var value = value_src.val();
var html = '<div class="line">' +
'<input id="accepted" type="text" value="' + value + '" />' +
'<input type="button" value="X" class="remove" />' +
'</div>';
$(html).appendTo(container);
value_src.val('');
} else {
alert("You tried to add a field when there are already " + maxFields);
}
} else {
alert("You didn't enter anything");
}
})
.on('click', '.remove', function () {
$(this).parents('.line').remove();
});
You can add a class to each row like form-row
var html = '<div class="line form-row">' +
'<input id="accepted" type="text" value="' + value + '" />' +
'<input type="button" value="X" class="remove" />' +
'</div>';
and count the length by using
console.log($(container).find('.form-row').length);
// Use +1 because initially it is 0
Fiddle http://jsfiddle.net/9sX6X/69/
You can make use of the placeholder property to identify which button triggered the function.
value_src.attr('placeholder');
This string can then be used to access three different counters in an associative array.
Code
var maxFields = 10;
var currentFields = new Object;
$('.form').on('click', '.add', function () {
var value_src = $(this).prev();
var container = $(this).parent().prev();
if ($.trim(value_src.val()) != '') {
var identity = value_src.attr('placeholder');
if(currentFields[identity] == undefined)
currentFields[identity] = 0;
if (currentFields[identity] < maxFields) {
var value = value_src.val();
var html = '<div class="line">' +
'<input id="accepted" type="text" value="' + value + '" />' +
'<input type="button" value="X" class="remove" />' +
'</div>';
$(html).appendTo(container);
value_src.val('');
currentFields[identity]++;
} else {
alert("You tried to add a field when there are already " + maxFields);
}
} else {
alert("You didn't enter anything");
}
})
.on('click', '.remove', function () {
$(this).parents('.line').remove();
currentFields--;
});
JSFiddle: http://jsfiddle.net/9sX6X/73/
I'm trying to get the values of some input tags for doing some validation before continuing. My form is located inside of a jQuery Dialog box of which the HTML is dynamically generated based on the number of elements within a JSON array like so -
if (testDialog === null)
{
myTestDialogContentDiv += '<div id="TestDialog" style="padding-left: 0; top: 0px; left: 0px;">';
}
myTestDialogContentDiv += '<div id="TestDialogWarning" class="ClockInner"></div>';
myTestDialogContentDiv += '<div id="TestDialogText" class="ClockInner" style="position: relative;"></div>';
myTestDialogContentDiv += '<div class="TestDialogTxt"></div>';
myTestDialogContentDiv += '<form>'; //Start Form
myTestDialogContentDiv += '<p><b>Routing Out:</b></p>';
if (data.routesout.length > 1)
{
for(i=0;i<data.routesout.length;i++)
{
myTestDialogContentDiv += '<label for="route' + i + '">' + data.routesout[i].name + '(%)</label>';
myTestDialogContentDiv += '<input onkeypress="validateKeypress(event)" type="text" name="route' + i + '" id="route' + i + '" value="' + data.routesout[i].percent + '" maxlength="5" size="8" class="ui-widget-content ui-corner-all">';
myTestDialogContentDiv += '</br>'
}
}
else
{
myTestDialogContentDiv += '<label>' + data.routesout[0].name + '(%)</label>';
myTestDialogContentDiv += '<input type="text" name="route0" id="route0" disabled value="' + data.routesout[0].percent + '" maxlength="5" size="8" "class="ui-widget-content ui-corner-all">';
}
And this is my code for creating a Dialog box with the form data embedded in it, along with my "on submit" validation.
TestDialog = $("#TestDialog");
TestDialog.dialog({
title: data.name,
resizable: true,
closeOnEscape: true,
zIndex: 1000,
dialogClass: 'outerGlow hideCloseX testDialog',
buttons: {
"Save":function() {
//Need to check that all the fields add up to EXACTLY 100%
var total = 0;
for(var i=0; i< data.routesout.length; i++)
{
total += ("#route" + i).val();
}
if (total !== 100)
{
alert("NOT EQUAL TO 100!!!");
}
else
{
//TODO - Add Requests to update objects
$(this).dialog("close");
}
},
"Cancel": function() { $(this).dialog("close"); }
}
});
I'm getting a Jscript error saying that .val doesn't exist for that element, when I try to use Jscripts own .value I get a NaN. I think it's something to do with the form technically being a child node? But nonetheless I'm stumped, any help would be great.
Also ignore any spelling mistakes or inconsistencies in my spellings of ids etc, I quickly changed it to Test for posting.
Thanks!
total += ("#route" + i).val(); should be total += parseInt($("#route" + i).val());
I'm trying to limit inserting elements to the page:
<script type="text/javascript">
$(function() {
var i = 1;
//allow only 3 elements
if (i < 4) {
$('#add').click(function() {
var add_input = '<input type="file" />'
var add_link = 'Remove'
$('body').append('<p>' + add_input + add_link + '</p>');
});
i++;
}
$('.remove').live('click', function() {
$(this).parent('p').remove();
});
});
</script>
But I can still add element a lot more than 4.
You need to check your variable i within your event handler.
$('#add').click(function() {
if(i < 4){
var add_input = '<input type="file" />'
var add_link = 'Remove'
$('body').append('<p>' + add_input + add_link + '</p>');
i++;
}
});
And you should decrease i within your live() handler.
See a working example : http://jsfiddle.net/CtGgg/
You could count the number of elements already on the page and limit it that way. Personally, I like treating the DOM itself as the canonical representation of user state. If that's important to you, you could do something like the following, even though it's a little less performant:
$('#add').live('click', function (evt) {
if ($('input[type=file]').length < 4) {
$('body').append('<p><input type="file"> Remove</p>');
}
evt.preventDefault();
});