Adding checkboxes dynamically in jquery and validation check - javascript

I have a small issue. I have a main category that consists of a row of checkboxes. In this main category, I have a button Add Section, which adds another row of checkboxes under the above row and keep adding another row of checkboxes after each click on the Add Section.
Outside the box, I have a main button that allows adding another main category. The principle is the same, it adds a row of checkboxes, followed by another section button. And if I want to add another row again in this category, I just click on the Add Section button.
The issue is I am having, I am unable to add another row on clicking the Add section button. Also, I want to validate the as from the second row checkboxes and ownwards, such that if I check the first checkbox in the second row, I should be able to check the first checkbox in the third row.
The first row of checkboxes in the main category is independent of the second row of checkboxes and the onwards rows (that is the rows created on adding a section
I have done the validation as in : https://jsfiddle.net/fL3hekhw/
EDITED
The demo is : https://jsfiddle.net/fL3hekhw/
When I click on Add Section button in a box, it should not duplicated the added checkboxes in other boxes. How can I prevent this ? Please help.
Can someone please help me with this ? I am totally stuck.

There are a few issues with the demo you linked to.
You were asking for .closest('.js-cars-items') but you only used .js-cars-item as a class
When you added new checkboxes you were re-using ids, which must be unique across the whole document
When you were adding new categories, you were not registering the 'change' event listener with the new .cars element that you appended
I've made a few minor refactorings that I hope make the code a bit easier to read. I also removed the troublesome .closest('.js-cars-items') call completely because you were already iterating over .js-cars-item anyway.
I'm only unsure about one thing, though. Do you want checkboxes in a column to be validated across all categories or per category?
let nextSection = 4;
const carsItemSelector = '.js-cars-item [type="checkbox"]';
function registerValidation() {
$(".main").on("change", carsItemSelector, validateCategorySelection);
}
function validateCategorySelection() {
const idx = $(this).closest('li').index(); //Get the index - Number in order
const chk = $(this).is(":checked"); //Get if checked or not
const obj = this; //Checkbox object
$('.js-cars-item').each(function() { //Loop every js-cars-item
//Find the checkbox with the same index of clicked checkbox. Change disabled property
$(this).find('li:eq(' + idx + ')')
.find('[type="checkbox"]')
.not(obj)
.prop("checked", false);
});
var checkeds = [];
$(".cars-item input:checkbox:checked").each(function(index) {
checkeds[index] = $(this).attr('id');
});
console.clear();
console.log("These are checked:", checkeds);
}
function checkbox(index, section) {
return `
<li>
<input type="checkbox" id="car-${index}-${section}">
<label for="car-${index}-${section}"><i class="icon-tick"></i></label>
</li>
`;
}
registerValidation();
$('.js-add-category').click(function() {
const section = nextSection;
nextSection++;
var categoryContent =
`<div class="cars">
<div class="cars-item js-cars-item">
<ul>
${[1, 2, 3].map(i => checkbox(i, section)).join('\n')}
</ul>
</div>
<button type="button" class="js-add-section">Add Section</button>
</div>
<br>`
$('.main').append(categoryContent);
// registerValidation();
});
$(document.body).on('click', 'button.js-add-section', function() {
const section = nextSection;
nextSection++;
var sectionContent =
`<div class="cars-item js-cars-item">
<ul>
${[1, 2, 3].map(i => checkbox(i, section)).join('\n')}
</ul>
</div>`
$(this).closest('.cars').append(sectionContent);
});
.cars-item {
border-bottom: 1px solid gray;
}
ul {
/* Added to fully show console in snippet */
margin: 2px;
}
li {
display: inline;
}
.cars {
box-sizing: content-box;
width: 250px;
height: auto;
padding: 10px;
border: 5px solid blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button type="button" class="js-add-category">Add Category</button> <br> <br>
<div class="main">
<div class="cars">
<div class="cars-item js-cars-item">
<ul>
<li>
<input type="checkbox" id="car-1-3">
<label for="car-1-3"><i class="icon-tick"></i></label>
</li>
<li>
<input type="checkbox" id="car-2-3">
<label for="car-2-3"><i class="icon-tick"></i></label>
</li>
<li>
<input type="checkbox" id="car-3-3">
<label for="car-3-3"><i class="icon-tick"></i></label>
</li>
</ul>
</div>
<button type="button" class="js-add-section">Add Section</button>
</div>
<br>
<br>

I'm not sure but I suspect the problem comes from not catching the click event on created buttons, right?
If you want to listen to events on elements that are added after document load, don't use .change() but use $(document).on('eventName', 'elementName', callbackFunction);
Read more here:
Event handler not working on dynamic content

Related

input radio does not hide content when unchecked

input radio does not hide content when unchecked, i can't make the content be hidden when the radio input is unchecked
how can I hide the content of the unmarked radio input?
clicking on another radio input is unchecked but does not hide the content
$('#alternar').click(function () {
$('#prueba').toggle();
});
$('#alternarx').click(function () {
$('#pruebax').toggle();
});
/* commented out because this select doesn't appear in the HTML:
$(".placeholder").select2({
placeholder: "Make a Selection",
allowClear: true
});
*/
function uncheckAndCheck(event) {
// gets all radios with the name prefix like 'custom-radio-'
// and uncheck all of them
document.querySelectorAll("input[type='radio'][name^='custom-radio-']").forEach(radio => {
radio.checked = false;
});
// checks the radio that triggered the click event
event.target.checked = true;
}
#prueba{
display:none
}
#pruebax{
display:none
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<input type="radio" class="new-control-input" name="custom-radio-1" id="alternarx" onclick="uncheckAndCheck(event)"/>
<div id="prueba"> Content1 </div>
<input type="radio" class="new-control-input" name="custom-radio-2" id="alternar" onclick="uncheckAndCheck(event)"/>
<div id="pruebax"> Content2 </div>
George's solution works, but is reliant upon the HTML never changing. If you add any element between the radio button and the div, it will break the functionality.
To answer your question related to JavaScript:
It's unnecessary to check and uncheck the other radio inputs. You just need to give them the same name attribute.
Second, you're .toggle()ing the divs on click. That might be why they're acting strangely. You're not checking if the radio button is selected or not, and that's going to result in them toggling even when you click them when they're already selected. Luckily, you can just listen for them to change states.
Third, you can hold a selector for the target of the radio button you want to show/hide in a data attribute, and use one function for all of this.
Fourth, why mix inline onclick attributes, when you're using jQuery? Just listen for the event using the built-in listeners in jQuery.
//jQuery shorthand for $(document).ready(function(){ to be sure your DOM has loaded:
$(function() {
//run this on page load, too. Necessary because browsers will remember which one is checked on a page *refresh*, and hides the target divs initially when nothing is checked:
$checkedRB = $(".rbToggleDiv:checked");
if($checkedRB.length > 0) {
toggleVisibleDivs($checkedRB);
} else {
toggleVisibleDivs(false);
}
//both radio buttons have the same class as well, so you can listen for either of them to change states:
$(document).on("change", ".rbToggleDiv", function(e) {
//this = radio button that has changed
var $thisRB = $(this); //turn it into a jQuery object
if($thisRB.prop("checked")) { //only do something if this RB is checked
toggleVisibleDivs($thisRB);
}
});
function toggleVisibleDivs($targetRB) {
if ($targetRB === false) { //no target sent in
//hide all
$(".pruebaDiv").hide(); //hide all divs
} else { //target sent in
if ($targetRB.data("target-div")) { //make sure the data is set
var targetSelector = $targetRB.data("target-div"), //grab the string from the data object
$targetDiv = $(targetSelector); //use it to select the target div
if ($targetDiv.length > 0) { //make sure the div is selected
//hide all divs with the same class:
$(".pruebaDiv").hide();
//then, show only the one you want visible, the $targetDiv:
$targetDiv.show();
} else {
console.error("Div not found!", targetSelector);
}
} else {
//data not set:
console.error("Data was not set.");
}
}
}
});
.pruebaDiv {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<!-- if they have the same names, they will act as a radio button list, and will act accordingly. Also, you should really choose more descriptive IDs and names: -->
<input type="radio" class="rbToggleDiv" name="rb-toggle-div" id="alternarx" data-target-div="#prueba" />
<input type="radio" class="rbToggleDiv" name="rb-toggle-div" id="alternar" data-target-div="#pruebax" />
<!-- for the sanity of the user, I've moved these two divs next to each other below the radio buttons so they don't move around: -->
<div class="pruebaDiv" id="prueba"> Content1 </div>
<div class="pruebaDiv" id="pruebax"> Content2 </div>
This is actually possible entirely with CSS. You can use the adjacent sibling combinator +, which affects an element immediately following the first.
#prueba{
display: none;
}
#pruebax{
display: none;
}
input:checked + #prueba,
input:checked + #pruebax {
display: block;
}
<input type="radio" class="new-control-input" name="custom-radio-1" id="alternarx" onclick="uncheckAndCheck(event)"/>
<div id="prueba"> Content1 </div>
<input type="radio" class="new-control-input" name="custom-radio-2" id="alternar" onclick="uncheckAndCheck(event)"/>
<div id="pruebax"> Content2 </div>

When click on button, show divs with checked checkbox using JQuery

I want to use JQuery on my Coldfusion application for showing/hiding div elements with checkbox checked/unchecked within the div.
Basically, in a view I show multiple divs elements, every div have also more divs inside, one of these internal divs contains an input type checkbox that could come checked or unchecked.
I also have three buttons in that view 'Active, Inactive, All'. When clicking on Active I want to show all div elements with checkbox checked, not showing the unchecked, and the other way around when clicking on Inactive.
<div class="btn-group ">
<button id="actives" type="button">Actives</button>
<button id="inactives" type="button">Inactives</button>
<button id="all" type="button">All</button>
</div>
<div id="apiDiv">
<cfloop array="#apis#" index="api">
<div class="card card-found">
<div class="card-header">
<cfif Len(api.iconClass)>
<i class="fa fa-fw #api.iconClass#"></i>
</cfif>
#structKeyExists( api, "name" ) ? api.name : api.id#
</div>
<div class="card-body">
<p>#api.description#</p>
</div>
<div class="card-button">
<input class="#inputClass# ace ace-switch ace-switch-3" name="#inputName#" id="#inputId#-#api.id#" type="checkbox" value="#HtmlEditFormat( api.id )#"<cfif ListFindNoCase( value, api.id )> checked="checked"</cfif> tabindex="#getNextTabIndex()#">
<span class="lbl"></span>
</div>
</div>
</cfloop>
</div>
I´m not an expert at all with JQuery. The only thing I have done is what follows and I do not know whether if is a good beggining or not:
$("#actives").click(function (e) {
$("#apiDiv .card").filter(function() {
<!--- code here --->
});
});
Someone please that can help me with it? Thanks a lot in advance!
After your CF code executes, it will generate a .card for each loop iteration of your apis array. So you jQuery code will need a click handler for the #actives button and that will loop through each() iteration of the checkboxes to determine the checked/unchecked state. At that point find the closest() ancestor .card and show()/hide() the .card depending upon the checkbox state.
$("#actives").click(function (e) {
$('input[type=checkbox]').each(function() {
if (this.checked) {
$(this).closest(".card").show();
} else {
$(this).closest(".card").hide();
}
});
});
If you want to do it with jQuery code:
$('#actives').click(function(){
$('#apiDiv').show();
});
Working Fiddle
The code you are probably looking for is in these event handlers for your buttons:
function activesHandler() {
jQuery(".card-button > input:checked").parents(".card.card-found").show();
jQuery(".card-button > input:not(:checked)").parents(".card.card-found").hide();
}
function inactivesHandler() {
jQuery(".card-button > input:checked").parents(".card.card-found").hide();
jQuery(".card-button > input:not(:checked)").parents(".card.card-found").show();
}
function allHandler() {
jQuery(".card.card-found").show();
}
jQuery("#actives").click(activesHandler);
jQuery("#inactives").click(inactivesHandler);
jQuery("#all").click(allHandler);
I reproduced some of your ColdFusion by replacing it with JavaScript and provided a demonstration of the above event handlers in this JSFiddle.
Call the checkbox by its id and when it's checked, write a function to display the divs you want to display:
<input type="checkbox" id="check">
$document.getElementById("check").onclick = function(){
$document.getElementById("div_name").style.display="block"; // block displays the div.
}

How do I display a same div for a number times that user input in jquery?

I have POS system with cheque payments. when the cashier input the number of cheque according to the input the cheque detail form should generated.
Eg : if he enter Number 5, the same form should be display five times How can i do this with jquery.
I have attached up to what i have done so far !!
Thanks in Advance
This is the user input
<input type="number" class="form-control" id="numberOfChq" >
<a id="come" class="btn btn-primary">Submit</a>
This is the div to be repeated
<div id="chk_list" hidden></div>
This is the jquery i tried its displaying only once, i want to diplay as many user input
$("#come").click(function(){
var chqNumebr = $("#numberOfChq").val();
var i;
for (i= 1; i <= chqNumebr; i++ ){
var chqSh = $("#chk_list").slideDown("slow");
}
});
Try the below.
First we need something to add the new divs into, so I created <div id="output"></div> for that.
After pressing submit, you'll see the new divs get added according the number the user entered. But we have to make sure that we empty #output every time the function runs otherwise the newly created divs would just keep adding onto the existing ones.
Secondly, if we are going to have multiple instances of #chk_list then it shouldn't have an ID as all ID's should be unique. Instead, we'll use a class.
$("#come").on('click', function() {
var chqNumebr = $("#numberOfChq").val();
//empty divs that are currently inside of #output
$('#output').empty();
for (var i = 0; i < chqNumebr; i++) {
$('#output').append('<div class="chk_list"></div>')
}
});
.chk_list {
width: 50px;
height: 30px;
background: red;
margin-top: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="number" class="form-control" id="numberOfChq">
<a id="come" class="btn btn-primary">Submit</a>
<div id="output"></div>

Issue Sorting Checkbox Labels according to state (checked at buttom, unchecked on top)

I'm working on creating a grocery-list-like checklist with custom checkboxes. When checking off an item I using Javascript to move the item to the bottom of the list and strike it. This all works as it should, but I would also like to place it at the buttom of the list of unchecked should it be unchecked. This is were I can't seem to get it right. It seems that I keep appending the node to the opposite end (counting from the bottom up) instead of from the top down no matter how I try to insert it. My javascript function looks like this
function got(cbId) {
var cbox = document.getElementById(cbId);
var lbl = cbox.nextElementSibling;
var par = cbox.parentNode;
var list = document.getElementById('list');
var newlbl = document.createElement('LABEL');
if(cbox.checked){
par.insertBefore(newlbl,lbl);
newlbl.outerHTML = '<label for="'+cbId+'" class="name got"><strike>'+lbl.innerHTML+'</strike></label>';
par.removeChild(lbl);
list.removeChild(par);
list.appendChild(par);
}else{
var tmp = lbl.innerHTML;
tmp = tmp.replace(/<strike>/g,'');
newlbl.innerHTML = tmp.replace(/<\/strike>/g,'');
par.insertBefore(newlbl,lbl);
newlbl.outerHTML = '<label for="'+cbId+'" class="name">'+newlbl.innerHTML+'</label>';
par.removeChild(lbl);
list.removeChild(par);
var totItems = list.getElementsByClassName('name');
var gotItems = list.getElementsByClassName('name got');
var bottom = totItems.length - gotItems.length;
list.insertBefore(par,list.childNodes[bottom]);
console.log(bottom);
//list.childNodes[lastGot]
}
}
The last line list.insertBefore(par,list.childNodes[totItems.length]); is the line that deals with moving the node. I've tried list.childNodes[totItems.length] and list.childNodes[bottom], but both ways don't work for me. Here's a sample of the html that comprises the list
<div id="list">
<div class="item">
<input id="item1" type="checkbox" onclick="got(this.id);" class="box">
<label for="item1" class="name">Apples</label>
</div>
<div class="item">
<input id="item2" type="checkbox" onclick="got(this.id);" class="box" >
<label for="item2" class="name">Bananas</label>
</div>
<div class="item">
<input id="item3" type="checkbox" onclick="got(this.id);" class="box" >
<label for="item3" class="name">Stawberries</label>
</div>
</div>
Below are a few screenshots of how it works as of right now.
The numbers are the order in which they are clicked
The result after the two items have been clickedEach click sends the item to the bottom of the list.
What happens when unchecking BananasThe item is not put at the bottom of the list of unchecked. The arrow shows where it should've went (right above Strawberries). Also, if only one item is checked, if that one item is unchecked it should stay at the bottom of the list.
How can I make this work as I would like? What am I doing wrong?
Here is the Liveweave and JSFiddle for a working example of the code I currently have.
Note: I would like to avoid jQuery as the application I'm using this for can only do javascript.

Hide an HTML form field when a button is clicked and replace it with a different field

I have an html form that has a field that needs to become hidden and replaced with another when a button is clicked. I can't get rid of this field altogether because its value still must be submitted. Here is some sample code for reference:
<select id="Id.0" onChange="changeTextBox();">
<input type="button" id="addButton" value="Add" onclick="addQual();"/>
Basically what needs to happen is when the addButton is clicked, Id.0 must disappear (but remain a member of the form) and be replaced by an identical field with id="Id.1" then upon clicking again id="Id.2" and so on.
Is there a way, using JavaScript or jQuery, to hide and replace this field upon clicking this button? Thanks!
This with jQuery might help.
elmCount = 0;
function addQual()
{
$("#Id." + elmCount).css('visibility', 'hidden');
$("#Id." + elmCount).css('height', '0px');
elmCount += 1;
}
Thanks to comments.
<div id="divAny">
<select id="Id.0" onChange="changeTextBox();">
</div>
<input type="button" id="addButton" value="Add" onclick="addQual();"/>
var index = 0;
function addQual(){
$("#divAny").hide();
$("#Id."+index).attr("id" , "Id."+ (++index));
}
As an alternative to #MahanGM's answer, I would minimise the use of jQuery here and do only the following in your addQual function:
addQual = function() {
$('select').toggleClass('hidden');
}
You then need a css class hidden to hide the required element. As others have said, you must not use display: none if you don't want to lose the value of the input.
.hidden {
visibility: hidden;
height: 0;
}
And you start out in your markup with both selects present, only the one you initially want hidden has the appropriate class:
<select id="Id.0">
<select id="Id.1" class="hidden">
<input type="button" id="addButton" value="Add" onclick="addQual();"/>
A basic example with spans: http://jsfiddle.net/5Dayf/1/
Cleanest solution in my eyes: see here jsFiddle
HTML, nothing special:
<select class="replaceableSelect" id="Id.0">
<option name="one" value="one">One</option>
</select>
<button id="addButton">Add</button>
Javascript using jQuery:
$(document).ready(function () {
var changeTextBox = function () {
/** Your code goes here */
};
// add the onchange event to all selects (for the current one and future ones)
$(document).on("click", "select.replaceableSelect", changeTextBox);
var currentId = 0,
currentSelect = $("#Id\\.0");
$("#addButton").on("click", function (e) {
// hide the old select
currentSelect.addClass("invisible");
// create the new select with increased id and add onchange event
currentSelect = $('<select class="replaceableSelect" id="Id.' + (++currentId) + '"><option name="two" value="two">Two</option></select>').insertAfter(currentSelect).bind("change", changeTextBox);
});
});
CSS:
.invisible{
visibility: hidden;
height: 0;
width: 0;
margin: 0;
padding: 0;
border: none;
}
Hint: To process the results of your form, please make sure, every select gets a unique name.

Categories

Resources