How to get value/values of buttons created using twitter bootstrap? - javascript

I'm using the following HTML code for button creation. I've applied the classes from bootstrap to these buttons.
<label class="help-block" for="xlInput">Monetization</label>
<div id="revsource" class="btn-group" data-toggle="buttons-checkbox">
<button id="revenueSource" class="btn monibtn active" value="1" data-toggle="button" type="button">Advertise</button>
<button id="revenueSource" class="btn monibtn" value="2" data-toggle="button" type="button">License</button>
<div class="controls">
<input id="revenueSource1" type="hidden" 0="0" name="data[RevenueSource][revenue_source_id]" value="1,2">
</div>
</div>
Now what I want is the value or values of the buttons selected by user. Means if user selects button 1 then I want the concerned value of button 1. If he selects button 2 only then the concerned value of button 2 I should get and if user selects both the buttons then I should get the values of both buttons. For achieving this I tried following code but it didn't work. Can anyone please help me out in this thing? Thanks in advance.
$('.monibtn').click(function(){
var selected = [];
$('.monibtn').each(function(){
if($('.monibtn').hasClass('active')) {
selected.push($(this).val());
$('#revenueSource1').val(selected);
}
});
});

You can use .map() along with the target selector .monibtn.active
$('.monibtn').click(function () {
//get all .monibtn elements with class active and create an array with the value of those elements
var selected = $('.monibtn.active').map(function () {
return this.value;
}).get();
//assing the value of the selected array to the target element
$('#revenueSource1').val(selected.join());
});

Related

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 make DOM/event listeners aware of newly appended nodes?

TL;DR:
I use $(..).append(node), but newly added nodes are not considered for inclusion despite them (supposedly) matching jQuery selectors.
Question
I have some code below that uses checkboxes but emulates radio button behavior. In other words, only one checkbox can (validly) be selected at any time. No more than one should be selected.
If you run the example below and click on the first 3 checkboxes, they will behave like radio buttons. Only one will be selected, no matter how many you click.
However, if you Add Point, newly added points will not be considered for the JS even though in theory it should grab them too...
Specifically: You can select the newly added checkbox, and it will be selected in addition to one already selected previously. That is incorrect as only 1 should be selected at any time and all others should be unselected.
What is happening and how can I have newly added nodes be included into jQuery selectors?
$(function() {
//check first box
$("input.duty:first").prop("checked", true);
//clicking unchecked box should check that box
//unchecks all others
$(".duty").on('click', function(event) {
$("input.duty").prop("checked", false);
$(this).prop("checked", true);
});
$("#addCasePoint").on("click", function() {
var newRowIndex = $('#newRowIndex').text();
var template = $('#casePointTemplate').data('template');
template = template.replace(/__index__/g, newRowIndex);
$('#casePointsFieldset').append(template);
$('#newRowIndex').text(++newRowIndex);
return false;
});
//deletes case point
$("#selection").on("click", ".removeCase", function() {
var caseCount = $('#selection .casePointFieldset').length
if (caseCount === 1) return false; //keep at least one row
$(this).closest("fieldset").remove();
return false;
});
});
.casePointFieldset {
display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id="selection">
<fieldset id="casePointsFieldset">
<legend>Case Points</legend>
<div id="pointFieldset">
<fieldset class="casePointFieldset">
<div>
<label><span>Duty:</span> <input name="point[1]" class="duty" value="1" type="checkbox"></label>
</div>
<button class="removeCase">Remove</button>
</fieldset>
<fieldset class="casePointFieldset">
<div>
<label><span>Duty:</span> <input name="point[1]" class="duty" value="1" type="checkbox"></label>
</div>
<button class="removeCase">Remove</button>
</fieldset>
<fieldset class="casePointFieldset">
<div>
<label><span>Duty:</span> <input name="point[1]" class="duty" value="1" type="checkbox"></label>
</div>
<button class="removeCase">Remove</button>
</fieldset>
</div>
<!-- include template -->
<span id="casePointTemplate" data-template="<fieldset class="casePointFieldset"><div><label><span>Duty:</span> <input name="point[__index__]" class="duty" value="1" type="checkbox"></label></div><button class="removeCase">Remove</button></fieldset>">
</span>
</fieldset>
<button id="addCasePoint">Add Point</button>
</form>
The problem is how you're binding to them. The .click function (or .on('click')) basically works like this:
Find all of the currently existing elements which match a selector ($('.your.selector.here'))
Attach an event handler to each of those elements
Notice how I mentioned it binds to ones which already exist? That means it won't bind to newly created ones automatically. However, you can use .on to bind to the parent of those elements then listen for events on a selector. I'll show you what I mean:
$('#addItem').click(function() {
$('.container').append('<button class="item">Item</button>');
});
// Notice that I'm binding to the parent
// then specifying which events from it's children
// I want to listen to (click events from .item elements)
$('.container').on('click', '.item', function() {
console.log("I'm an item");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<button class="item">Item</button>
</div>
<button id="addItem">Add New Item</button>
If you change your on('click' to work like that then you'll have no problems.
Easiest way will be, attaching the event to the document. In the past this was done with the live() method.
$(document).on('click', '.duty', function(event) {
$("input.duty").prop("checked", false);
$(this).prop("checked", true);
});

Change between menu/buttons

So I've got this menu where you can choose the class in my game.
<div class="text">
<div id="story">Choose a class.</div>
<input type="button" class="knight" value="Knight"/>
<input type="button" class="mage" value="Mage"/>
<input type="button" class="archer" value="Archer"/>
</div>
How do I use jquery so that when I press any of these buttons, I'll get a new set of buttons which you can press to choose your race?
I've tried .replaceWith() but jquery won't work on the new buttons.
It will take the css.
function classChange() {
var Class = $(this).val();
$('#statsImg').text("class: " + Class);
$('.knight').replaceWith('<input type="button" class="elf value="Elf"/>');
$('.mage').replaceWith('<input type="button" class="human" value="Human"/>');
$('.archer').replaceWith('<input type="button" class="Dwarf" value="Dwarf"/>');
$('.menu').show();
};
$('.knight').click(classChange);
$('.mage').click(classChange);
$('.archer').click(classChange);
Button elf won't do anything with the next part:
$('.elf').on('click', '.elf',function () {
$('#statsImg').text('test');
});
Works with button knight/mage/archer.
So what I'd like to know is how do I get rid of this menu and get a new menu once I press a button?
Sorry if I forgot to add something that you need to know. I'll add it if you need it.
You have to bind the events to the buttons after adding them. Try with -
$('.knight').replaceWith('<input type="button" class="elf value="Elf"/>').bind('click', function() {
$('#statsImg').text('test');
});

Hide existing <div> and show previous <div> in multi-branch form

I will start by telling you that this is my very first Javascript program from scratch. I am trying to make a back button that will go to the previously chosen div in a form (hide the current div and show the previous one the user chose).
The form has multiple paths to follow, paths within paths and not all selectors are buttons. There might be an onchange event or a radio button or even text input (text inputs have a next button to click).
I have had it working where it will hide the current div but show all previous chosen divs. It's now working where it hides the current div but shows nothing.
I have read a bunch of postings here and in other forums but have not found what I need yet. Any help would be greatly appreciated.
You can see the actual site here and I have put up a JSfiddle but for some reason I can't get it working there.
Here is the code from the fiddle:
<div>
<form>
<div id="uno" class="showFirst">
<button onclick="hideUno()">First Button</button>
</div>
<div id="dos" class="hideFirst">
<button onclick="hideDos()">Second Button</button>
</div>
<div id="tres" class="hideFirst">
<button onclick="hidetres()">Third Button</button>
</div>
<div id="quattro" class="hideFirst">
<button onclick="hideQuattroUno()">Fourth Button</button>
<button onclick="hideQuattroDos()">Fifth Button</button>
</div>
<div id="branchUno" class="hideFirst">
<p>First Branch</p>
</div>
<div id="branchDos" class="hideFirst">
<p>Second Branch</p>
</div>
</form>
<button id="backButton" onclick="goToPrevious" class="hideFirst">Back</button>
</div>
.hideFirst {
display: none;
}
function goToPrevious() {
var current = $(".chosen").find(":visible");
$(current).hide();
$(current).prev(".chosen").show();
}
function hideUno() {
$("#backButton").toggle();
$("#uno").toggle();
$("#uno").addClass("chosen");
$("#dos").toggle();
}
function hideDos() {
$("#dos").toggle();
$("#dos").addClass("chosen");
$("#tres").toggle();
}
function hideTres() {
$("#tres").toggle();
$("#tres").addClass("chosen");
$("#quattro").toggle();
}
function hideQuattroUno() {
$("#quattro").toggle();
$("#quattro").addClass("chosen");
$("#branchUno").toggle();
}
function hideQuattroDos() {
$("#quattro").toggle();
$("#quattro").addClass("chosen");
$("#branchDos").toggle();
}
Here are a few of the questions I've reviewed here:
retain show / hide div on multistep form
Hide and Show div in same level
how to show previous div of clicked div in angular.js
show div and hide existing div if open with jQuery?
Show one div and hide the previous showing div
I realize it's not the cleanest code, but as I said this is my first and I am trying to cleanup as I go along and learn new things.
You could make a bit of automatization instead of creating onclick events for each button/select separately.
For "Back" functionality, I'd use an array to store elements "on the fly" at each step, instead of checking visibility later on.
I'll make it this way:
Remove CSS rule display:none for hideFirst class (elements will be hidden using jQuery).
Add an class to the buttons/selects/check-boxes/etc... as event inndicator.
Add data-next attribute (to store id of the element which should be shown on click/change)
HTML:
<div id="firstDiv" class="hideFirst">
<button class="my-btn" data-next="#secondDiv" type="button">Show next<button>
</div>
<div id="secondDiv" class="hideFirst">
<select class="my-select" data-next="#thirdDiv">
<option>Helo World</option>
...
</select>
</div>
...
Script:
$(document).ready(function(){
// hide all 'hideFirst' elements, except the first one:
$('.hideFirst:not(:first)').hide();
// declare 'history' variable as an empty array (it will be used to store 'hideFirst' elements for 'Back' functionality):
var history = [];
// click event for the buttons :
$('.my-btn').click(function(e){
// as the button will submit the form if you're not using type="button" attribute, use this:
e.preventDefault();
showNext($(this));
});
// change event for selects :
$('.my-select').change(function(){
showNext($(this));
});
// Method used to show/hide elements :
function showNext(el){
// check if element has a 'data-next' attribute:
if(el.data('next')){
// hide all elements with 'hideFirst' class:
$('.hideFirst').hide();
// show 'Back' button:
$('#backButton').show();
// show the element which id has been stored in 'data-next' attribute:
$(el.data('next')).show();
// Push the parent element ('.hideFirst') into history array:
history.push(el.closest('.hideFirst'));
}
}
// click event for 'back' button:
$('#backButton').click(function(){
// hide all elements with 'hideFirst' class:
$('.hideFirst').hide();
// remove the last '.hideFirst' element from 'history' array and show() it:
history.pop().show();
// hide 'back' button if history array is empty:
history.length || $(this).hide();
}).hide(); // hide 'back' button on init
});
DEMO

jQuery cannot recognize appended cloned elements using jQuery.appendTo()

I want to make a list of group inputs allow user to dynamically let user add/remove group row:
<div id="div-form-denominations" class="form-denominations">
<div id="row-0" class="form-denomination">
<div class="form-field">
<div class="form-field">
<div class="form-field">
<input id="_denominations[0].id.reference" class="removableHiddenOrder" type="hidden" name="denominations[0].id.reference" value="87-070329-034COP-4444">
<input id="_denominations[0].denomination" class="removableHiddenDenom" type="hidden" name="denominations[0].denomination" value="10000">
<a id="deleteBtn-[0]" class="action-link delete-denomination" href="#">
<div class="spacer"></div>
</div>
<div id="row-1" class="form-denomination">
<div class="form-field">
<div class="form-field">
<div class="form-field">
<input id="_denominations[1].id.reference" class="removableHiddenOrder" type="hidden" name="denominations[1].id.reference" value="87-070329-034COP-4444">
<input id="_denominations[1].denomination" class="removableHiddenDenom" type="hidden" name="denominations[1].denomination" value="">
<a id="deleteBtn-[1]" class="action-link delete-denomination" href="#">
<div class="spacer"></div>
</div>
<div id="row-2" class="form-denomination">
<div class="form-field">
<div class="form-field">
<div class="form-field">
<input id="_denominations[2].id.reference" class="removableHiddenOrder" type="hidden" name="denominations[2].id.reference" value="">
<input id="_denominations[2].denomination" class="removableHiddenDenom" type="hidden" name="denominations[2].denomination" value="">
<a id="deleteBtn-[2]" class="action-link delete-denomination" href="#">
<div class="spacer"></div>
</div>
<div id="row-3" class="form-denomination">
.......
</div>
So each row include a group of form-field which include an input or select component(not show in above code) and some hidden fields and a delete link to remove current row from view.
Also I create a link to dynamic add a new row into the section
var rowTemplate = null;
j(document).ready(function() {
// Save the row template
rowTemplate = j('.form-denomination:first-child').clone();
j("#add_link").click(function() {
add_denomination();
});
});
and here is the content of add_denomination function that clone the first row and replace any cloned id with new index, and append the cloned row after last row of the list.
function add_denomination() {
var index = j('.form-denomination').length;
// set the new row id
var newRowId = 'row-' + index;
var newRow = rowTemplate.clone().attr('id', newRowId);
// Replace the id/name attribute of each input control
newRow.find('div, input, select, a').each(function() {
replaceAttribute(j(this), 'id', index);
replaceAttribute(j(this), 'name', index);
j(this).val('');
});
// add new element to the DOM
newRow.appendTo('.form-denominations');
alert("new list size = " + j(".delete-denomination").length);
console.log("DONE!");
}
each time click on the add-link the pop up alert show the new list size (j(".delete-denomination").length increment by 1), which in my understanding, new row appended successfully.
The problem is the following method
// delete denomination row
j('.delete-denomination').click(function () {
j(this).parent().remove();
}
ONLY WORKS FOR THE NON-CLONED ROW !!! Using firebug I can clearly see the appended row is successfully appended with same structure and same element as original rows but only difference is the id.
However, each time when I click on deleteBtn-[i], in which i is the cloned/appended row's index, the code even not going into the j('.delete-denomination').click() function, which in my understanding, Dom or jquery didn't recognize the new rows hence the failure of identifying the link by jQuery. It's kind of contradictory to the previous alert message that telling the size of list has grown.
But when I click on deleteBtn-[i] where i is the non-cloned row, everything works fine...
So the question is: how to append/add new doms and make them identified by jQuery or Dom? What is wrong in above processing? Is there any way to refresh the list so that Dom/jQuery understand the appended rows from all perspective?
jQuery 1.7+
j(".form-denomination").on("click", ".delete-denomination", function(){
j(this).parent().remove();
});
jQuery 1.3+
j(".delete-denomination").live("click", function(){
j(this).parent().remove();
});
jQuery 1.4.3+
j(".form-denomination").delegate(".delete-denomination", "click", function(){
j(this).parent().remove();
});
The problem is a matter of order and when expressions are evaluated. When you call jQuery with a selector, the selector is evaluated at that time to select the matching elements which exist at that time. The click handler is then registered to only those elements. Elements which are created later are, naturally, not affected.
One solution, demonstrated in another example, uses jQuery's "live events" to apply the selector at the time each event is fired to determine what elements, if any, it would match. There is a performance implication to this approach.
Another solution is to register the desired event handler on the newly created elements when you create them.
Add 'true' to the clone method in order to copy the data as well as the events attached to the original element.
rowTemplate = j('.form-denomination:first-child').clone(true);
This is disabled by default. Here is the clone documentation:
https://api.jquery.com/clone/
P.s. You don't need the click function within the document.ready and it won't bind until after the click.

Categories

Resources