Twitter bootstrap managing multiple radio buttons through Javascript in rails - javascript

I am using twitter bootstrap in my rails app, and I am constructing a form with multiple radio button inputs. In order to manage the form data, I have created a hidden field whose value is updated via Javascript.
Sample code below for any given input:
<div class="btn-group" data-toggle="buttons-radio">
<button type="button" class="btn" id="ornamental_only_yes" name="ornamental_only" value="yes">Yes</button>
<button type="button" class="btn" id="ornamental_only_no" name="ornamental_only" value="no">No</button>
</div>
<input type="hidden" id="ornamental_only" name="ornamental_only" value="">
Here is the Javascript to manage this event:
<script>
var btns = ['ornamental_only_yes', 'ornamental_only_no'];
var input = document.getElementById('ornamental_only');
for(var i = 0; i < btns.length; i++) {
document.getElementById(btns[i]).addEventListener('click', function() {
input.value = this.value;
});
}
</script>
My question: Is there a way to abstract the Javascript code in such a way as to apply to multiple radio button inputs simultaneously? (For instance, if I had 3 repetitions of the code block above with different id's)

Let's assume this is your HTML with multiple sets of buttons:
<div class="btn-group" id="btn_group_1" data-toggle="buttons-radio">
<button type="button" class="btn" id="ornamental_only_yes" name="ornamental_only" value="yes">Yes</button>
<button type="button" class="btn" id="ornamental_only_no" name="ornamental_only" value="no">No</button>
</div>
<input type="hidden" id="hidden_1" name="ornamental_only" value="">
<div class="btn-group" id="btn_group_2" data-toggle="buttons-radio">
<button type="button" class="btn" id="awesome_only_yes" name="awesome_only" value="yes">Yes</button>
<button type="button" class="btn" id="awesome_only_no" name="awesome_only" value="no">No</button>
</div>
<input type="hidden" id="hidden_2" name="awesome_only" value="">
To dynamically listen for clicks on all button groups, you could do something like this (untested jQuery):
$('.btn-group .btn').on('click', function() {
var parentID = $(this).parent().attr('id');
$('#hidden_' + parentID.substr(parentID.length - 1)).val($(this).val());
});
This just targets the hidden input fields based on the number at the end of the id.

Try using this:
for(var i = 0; i <= btns.length; i++) {

Use jQuery.
var buttonObjs = $(".btn-group").find("button");
buttonObjs.click(function(){
$("#ornamental_only").val(this.value);
});
To apply this code to multiple blocks, all you need to do is assign a specific class to the btn-group element, something like,
<div class="btn-group js_radio_toggle">
In the js code just use,
var buttonObjs = $(".btn-group.js_radio_toggle").find("button");
now this code can be reused anywhere.
also in your js code. you can do this,
document.getElementsByClassName("js_radio_toggle").
But I would recommend you to use jQuery.

Related

Is there a way to make every bouton using a single code

For a school project, I'm coding a porfolio.
I want to use jQuery hide() and show() to have popups that appear after clicking on buttons.
Is there a way, with a single code, to make every HTML element with the class="vignette" and an id="bouton1" show a div with the same number in id (id=popup1).
I don't know if I'm clear, I'm a student in graphic design, and I'm not having a good time.
As far as I can understand from your question, you want to show a modal whose ID is the same number as the button's ID?
You can use this same logic to work with your modal instead
// This regex just gets the number part from the ID
const re = /bouton(\d+)/
$('button.vignette').click(e => {
const res = re.exec(e.target.id)
if(res) {
// "popup" + res[1] gives the popup id
$('#content').html("popup" + res[1])
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class = "vignette" id = "bouton1">B1</button>
<button class = "vignette" id = "bouton2">B1</button>
<button class = "vignette" id = "bouton3">B1</button>
<button class = "vignette" id = "bouton4">B1</button>
<div id = "content"></div>
You can create a function that will be added via addEventListener. Alternatively you can add an onclick attribute to the HTML elements whose click you want to handle.
let activeDiv;
function myClick() {
if (activeDiv) activeDiv.classList.add("invisible");
(activeDiv = document.getElementById(this.id.replace("bouton", "popup"))).classList.remove("invisible");
}
let buttons = document.getElementsByClassName("vignette");
for (let button of buttons) {
button.addEventListener("click", myClick);
}
.invisible {
display: none;
}
<input type="button" id="bouton1" class="vignette" value="First">
<input type="button" id="bouton2" class="vignette" value="Second">
<input type="button" id="bouton3" class="vignette" value="Third">
<input type="button" id="bouton4" class="vignette" value="Fourth">
<input type="button" id="bouton5" class="vignette" value="Fifth">
<input type="button" id="bouton6" class="vignette" value="Sixth">
<input type="button" id="bouton7" class="vignette" value="Seventh">
<input type="button" id="bouton8" class="vignette" value="Eigth">
<input type="button" id="bouton9" class="vignette" value="Ninth">
<div id="popup1" class="invisible">1</div>
<div id="popup2" class="invisible">2</div>
<div id="popup3" class="invisible">3</div>
<div id="popup4" class="invisible">4</div>
<div id="popup5" class="invisible">5</div>
<div id="popup6" class="invisible">6</div>
<div id="popup7" class="invisible">7</div>
<div id="popup8" class="invisible">8</div>
<div id="popup9" class="invisible">9</div>
suppose you have 10 buttons with class vignette then you code would be:
$.each( "button.vignette", function( i, obj) {
$(obj).attr( "id", i ).on('click',function(){
$('#popup'+i).toggle();
});
});
You can replace toggle() function with your code as desired.

Dirty HTML or dirty jQuery for passing variables?

I have to pass variables to jQuery. There are two different approach as I see:
clean HTML, dirty jQuery:
<div class="itemContainer" data-id="1">
Item information
<input type="button" class="rename">
<input type="button" class="delete">
</div>
$('.rename').click(function() {
var id = $(this).parent().attr('data-id');
});
$('.delete').click(function() {
var id = $(this).parent().attr('data-id');
});
PROs:
clean, not redundant HTML,
CONS:
not so clean jQuery,
if the DOM structure changes, its hard to detect the errors, and it has to be fixed at 2 places
clean jQuery, dirty HTML:
<div class="itemContainer">
Item information
<input type="button" class="rename" data-id="1">
<input type="button" class="delete" data-id="1">
</div>
$('.rename').click(function() {
var id = $(this).attr('data-id');
});
$('.delete').click(function() {
var id = $(this).attr('data-id');
});
PROs:
clean jQuery,
works even DOM structure changes
CONS:
not so clean, redundant HTML,
which one would you prefer to use?
Your first HTML structure is the better implementation as it avoids repetition of the same data-id attribute.
With regard to the jQuery, you can use a single event handler by separating the selectors with a comma (,), and you can use closest() to find the required parent element. This is more robust as you can then change the HTML structure within that parent however you require and it will not break the JS logic, so long as the clicked element is still a child node. Finally, note that you should use data() to get/set data attributes where possible, not attr(). Try this:
$('.rename, .delete').click(function() {
var id = $(this).closest('.itemContainer').data('id');
console.log(id);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="itemContainer" data-id="1"> Item information
<input type="button" class="rename" value="Rename" />
<input type="button" class="delete" value="Delete" />
</div>
<div class="itemContainer" data-id="99"> Item information
<p>
Extra information...
<div class="another-child">
<input type="button" class="rename" value="Rename" />
<input type="button" class="delete" value="Delete" />
</div>
</p>
</div>
Put the selectors you want to add the listener to together in the selector string you use to add a .click listener to (separated by commas), and you don't need to repeat yourself at all:
$('.rename, .delete').click(function() {
var id = $(this).parent().attr('data-id');
console.log(id);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="itemContainer" data-id="1">
Item information
<input type="button" class="rename">
<input type="button" class="delete">
</div>
<div class="itemContainer" data-id="2">
Item information
<input type="button" class="rename">
<input type="button" class="delete">
</div>
You can combine the click event for both the element using Multiple Selector. You can specify any number of selectors to combine into a single result. This multiple expression combinator is an efficient way to select disparate elements.
clean jQuery, Clean HTML:
$('.rename, .delete').click(function() {
var id = $(this).parent().attr('data-id');
console.log(id);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="itemContainer" data-id="1">
Item information
<input type="button" class="rename">
<input type="button" class="delete">
</div>
I would use event delegation and a single data-attribute. You don't need jQuery for it. Added a button for restructuring the DOM to demonstrate that the handler keeps working after it.
(() => {
const evtHandler = evt => {
const origin = evt.target;
console.clear();
if (origin.id === "redoDOM") { return restructure(); }
if (origin.parentNode.classList.contains("itemContainer")) {
console.log(`${origin.classList} data-id: ${origin.parentNode.dataset.id}`);
}
};
document.addEventListener("click", evtHandler);
function restructure() {
if (!document.querySelector("#BttnContainer")) {
let container = document.createElement("div");
container.id = "BttnContainer";
container.innerHTML = `
<p>
div.itemContainer elements are wrapped.
Check if the button handler still works
</p>`;
Array.from(document.querySelectorAll(".itemContainer"))
.forEach(v => container.appendChild(v));
document.body.insertBefore(container, document.body.firstChild);
} else {
console.log("Already wrapped");
}
}
})();
#BttnContainer {
color: green;
}
<p>Click buttons to show data-id value of the surrounding element</p>
<div class="itemContainer" data-id="1">
Item information (1)
<button class="rename">rename</button>
<button class="delete">delete</button>
</div>
<div class="itemContainer" data-id="2">
Item information (2)
<button class="rename">rename</button>
<button class="delete">delete</button>
</div>
<p>
Click to wrap buttons in a new element
<button id="redoDOM">Restructure</button>
</p>

javascript two trigger function on input button

Hi i would like few textboxes disabled when a textbox contains a specific text and i click a button.
Here is what I have:
button:
<div id="itemRows1">
<label ></label><input type="hidden" name="add_name1" /><input onclick="addRow1(this.form); " type="button" id="dodaj1" value="Dodaj tip droge in količino" class="btn btn-primary" />
</div>
<br>
</div>
script:
<script>
var dis1 = document.getElementById("preiskavoopr1");
dis1.onchange = function () {
if (this.value == "SKP" ) {
document.getElementById("dolgnaziv").disabled = true;
var x = document.getElementsByClassName("form-control1");
var i = 0;
for (i = 0; i < x.length; i++) {
x[i].disabled = true;
}
} else {
document.getElementById("dolgnaziv").disabled = false;
}
}
</script>
The button is adding more fields dinamicaly and is working as expected.
The text box with the id preiskavoopr1 is a drop down with 2 values and is OK.
When i select a value SKP in the dropdown the text boxes with ClassName("form-control1"); has to become disabled and that is working. But when i click on the button 2 more text boxes with the ClassName("form-control1"); appears not disabled but they should be.
Hope i explained well enough.
It looks like you are trying to add onclick methods to <input> elements which disguised into a button because you added class="btn btn-primary" to it.
Change your button to
<button onclick="addRow()" class="btn btn-primary">Button Text</button>

Varying modal content based on trigger with input: radio and checkbox

I am using Net mvc4 in this project. I got a problem in my javascript where the
modal.find('modal-body input:radio[name=require_attachment][id=' + attachment+ ']').prop('checked', true);
It does not function properly. I also tried the jquery filter function:
modal.find('modal-body input:radio[name=require_attachment]').filter(['value=' + attachment+ '']).prop('checked', true);
Which has the same result, not working.
In my modal button that has data-* on with.e.g. data-attachment, I want to display it as a radio checked whether what value it return to the content of my modal.
<button type="button" class="btn btn-primary"
data-toggle="modal"
data-target="#Update_COA_Codes"
data-code="#item.code"
data-attachment="#item.require_attachment"
data-status="#item.status"
data-description="#item.description">Edit</button>
Inside my jquery script:
$('#Update_COA_Codes').on('show.bs.modal', function (event) {
var button = $(event.relatedTarget)
var attachment = button.data('attachment');
//... other code here
var modal = $(this);
modal.find('modal-body input:radio[name= require_attachment]')
.filter(['value=' + attachment + ''])
.prop('checked', true);
});
HTML modal-body
<div class="row top-buffer">
<div class="col-md-4">
<label><span class="red">*</span>Needs Attachments?</label>
</div>
<div class="col-md-4">
<input type="radio" name="require_attachment" value="true"> Yes
<input type="radio" name="require_attachment" value="false"> No
</div>
</div>
I'm not sure if this is the correct way of doing it. I'm open for any suggestions, thank you.

Displaying the selected value in JavaScript

i am using bootstrap btngroup to select one value ..how can i display that selected value ?? here is my code.
<div class="input-group">
<div id="radioBtn" class="btn-group">
<a class="btn btn-primary btn-sm active" data-toggle="fun" data- title="Y">YES</a>
<a class="btn btn-primary btn-sm notActive" data-toggle="fun" data-title="X">I don't know</a>
<a class="btn btn-primary btn-sm notActive" data-toggle="fun" data-title="N">NO</a>
</div>
<input type="hidden" name="fun" id="fun">
</div>
and JS
$('#radioBtn a').on('click', function(){
var sel = $(this).data('title');
var tog = $(this).data('toggle');
$('#'+tog).prop('value', sel);
$('a[data-toggle="'+tog+'"]').not('[data- title="'+sel+'"]').removeClass('active').addClass('notActive');
$('a[data-toggle="'+tog+'"][data-title="'+sel+'"]').removeClass('notActive').addClass('active');
})
Tidy your code - remove the spaces in your data- title attribute, in both the HTML and JS, as these are causing it to break.
Add a <div id="display"></div> in your HTML somewhere and style it how you like.
Add this line to your JS click handler: $('#display').html(sel);
Here's a demo.
If you'd prefer the result to be the text of the radio button instead of the value, use $('#display').html($(this).html()); instead in step 3.
Done.
Not sure if this is what you mean, but to get the value (or text) from a clicked button in a button group, I use for example.....
HTML
<div id="aBtnGroup" class="btn-group">
<button type="button" value="L" class="btn btn-default">Left</button>
<button type="button" value="M" class="btn btn-default">Middle</button>
<button type="button" value="R" class="btn btn-default">Right</button>
</div>
<p>
<div>Selected Val: <span id="selectedVal"></span></div>
JS
$(document).ready(function() {
// Get click event, assign button to var, and get values from that var
$('#aBtnGroup button').on('click', function() {
var thisBtn = $(this);
thisBtn.addClass('active').siblings().removeClass('active');
var btnText = thisBtn.text();
var btnValue = thisBtn.val();
console.log(btnText + ' - ' + btnValue);
$('#selectedVal').text(btnValue);
});
// You can use this to set default value upon document load
// It will fire above click event which will do the updates for you
$('#aBtnGroup button[value="M"]').click();
});
CONSOLE OUTPUT
Left - L
Middle - M
Right - R
Hope this helps
Plunker here

Categories