Utilizing ASP with DotNetNuke to loop through listing of repeating radio buttons.
Utilizing JQuery
Currently displaying proper result value for weightCalculations function (ex: 3)
How do I combine the rbtCalculations results with the weightCalculations results?
Ex: IF rbtCalculations = Very High AND weightCalculations = High THEN
$('p.custom' + ID).text("5");
<input id="rbt_0" name="rbt" value="Very High" checked="checked" onclick="rbtCalculations(this,6559);" type="radio">
<input id="rbt_1" name="rbt" value="High" onclick="rbtCalculations(this,6559);" type="radio">
<input id="stakeholders_rbt_0" name="stakeholders_rbt" value="Very High" onclick="weightCalculations(this,6559);" type="radio">
<input id="stakeholders_rbt_1" name="stakeholders_rbt" value="High" checked="checked" onclick="weightCalculations(this,6559);" type="radio">
<input id="stakeholders_rbt_2" name="stakeholders_rbt" value="Low to Moderate" onclick="weightCalculations(this,6559);" type="radio">
<p class="custom6559">3</p>
<script type="text/javascript">
function weightCalculations(value, ID) {
if (value.value == "High") {
$('p.custom' + ID).text("3");
}
else {
$('p.custom' + ID).text("2");
}
}
I'd probably just add a class to the radio buttons to identify them and a wrapping element to associate all the parts together:
<div class="js-weight-calc-wrap">
<input type="radio" class="js-rbt" ... />
<input type="radio" class="js-rbt" ... />
<input type="radio" class="js-weight" ... />
<input type="radio" class="js-weight" ... />
<input type="radio" class="js-weight" ... />
<p class="js-result custom6559"></p>
</div>
<script>
jQuery(document).ready(function ($) {
$('.js-rbt, .js-weight').change(function () {
var $this = $(this),
$wrap = $this.closest('.js-weight-calc-wrap'),
rbtVal = $wrap.find('.js-rbt:checked').val(),
weightVal = $wrap.find('.js-weight:checked').val(),
result = rbtVal === 'VeryHigh' && weightVal === 'High'
? '5'
: rbtVal === 'VeryHigh' && weightVal === 'Low'
? '4'
: '0';
$wrap.find('.js-result').text(result)
});
});
</script>
I'd also probably end up create a jQuery plugin to contain all of that logic, so on your page it'd just be a call like this:
jQuery(function ($) {
$('.js-weight-calc-wrap').weightCalculator({
rbtSelector: '.js-rbt',
weightSelector: '.js-weight',
resultSelector: '.js-result'
});
});
UPDATE
I'd forgotten before that you need to filter the radio buttons when you select them, so that you get the checked one only (was confusing with a <select/> element). After adding :select to the selector, it works as expected. I cleaned it up a little more, and created a working jsFiddle.
function weightCalculations(value, ID) {
if (value.value === "High" && $('input[name="rbt"]').val() === "Very High") {
$('p.custom' + ID).text("5");
}
else if(value.value === "High"){
$('p.custom' + ID).text("3");
}
else {
$('p.custom' + ID).text("2");
}
}
Related
I would like my program to automatically select all checkboxes (Specifically "Side 1, Side 2, Side 3 and Side 4") if the wall_amount input is above 3. How would this be done?
I have tried this on javascript lines 10-12. Thanks
HTML
<label for="wall_amount">Number of Walls</label>
<input type="number" value="1" min="1" max="4" step="1" id="wall_amount" name="wall_amount"></input>
<div>
Please choose where you want the walls placed
<label for="wall_side1">Side 1</label>
<input type="checkbox" id="wall_side1" name="wall_side1"></input>
<div style="display: inlineblock;">
<label for="wall_side2">Side 2</label>
<input type="checkbox" id="wall_side2" name="wall_side2"></input>
<img class="img2" src="images/reference.png" alt="Bouncy Castle">
<label for="wall_side3">Side 3</label>
<input type="checkbox" id="wall_side3" name="wall_side3"></input>
</div>
<label for="wall_side4">Side 4</label>
<input type="checkbox" id="wall_side4" name="wall_side4"></input>
</div>
Javascript
var base_length = Number(document.getElementById("base_length").value);
var base_width = Number(document.getElementById("base_width").value);
var walltype = Number(document.getElementById("walltype").value);
var checkbox_side1 = document.getElementById("wall_side1");
var checkbox_side2 = document.getElementById("wall_side2");
var checkbox_side3 = document.getElementById("wall_side3");
var checkbox_side4 = document.getElementById("wall_side4");
var wall_amount = Number(document.getElementById("wall_amount").value);
$("input:checkbox").click(function() {
let max = $("#wall_amount").val();
var bol = $("input:checkbox:checked").length >= max;
$("input:checkbox").not(":checked").attr("disabled", bol);
});
$("wall_amount").on('keyup', function () {
$('checkbox_side1').prop('checked', +$(this).val() > 3);
});
You can use the function setAttribute to check checkboxes. For example, this code (based on your example) will check your element with the id wall_side1.
checkbox_side1.setAttribute("checked", true)
Anyway, try adding this to your code as a function. Then add a conditional statement that runs the function every time your variable exceeds a certain amount.
I am still relatively new at answering questions so I hope this helps!
const checkboxes = [
"wall_side1",
"wall_side2",
"wall_side3",
"wall_side4"
].map((id) => document.getElementById(id));
const amountInput = document.getElementById("wall_amount");
amountInput.addEventListener("change", (event) => {
const value = parseInt(event.target.value || 0);
if (value === 4) {
checkboxes.forEach(
checkbox => {
checkbox.disabled = true;
checkbox.checked = true;
}
);
} else {
checkboxes.forEach(
checkbox => {
checkbox.disabled = false;
}
);
}
});
I'm using vanilla js, and I'm stumped because there's very little code here, so I'm not sure where the problem lies. It may be a misunderstanding on my part on how the attribute works.
function changeState() {
const self = event.target
const parent = event.path[1]
if (self.type == "radio") {
console.log(self.id + " is " + self.checked)
}
}
<div id="usernames_buttons">
<input type="radio" name="usernames" id="usernames-bl" onclick="changeState()" checked>
<label for="usernames-bl">BL</label>
</input>
<input type="radio" name="usernames" id="usernames-wl" onclick="changeState()">
<label for="usernames-wl">WL</label>
</input>
<button data-toggle onclick="changeState()">OFF</button>
</div>
I paired everything down to just this code and ran it in a code pen to test, and the console.log will return true regardless of which option I am clicking. The expectation is that usernames-bl would return true and -wl would return false, but they return true whether the checked attribute is there or not.
You are invoking the changeState() on every click and i guess, as its a radio button, which will always give checked 'true' on click
I think you are doing it right minus the "Off" button should un-check both.. so I added this block:
if (self.type != "radio") {
document.getElementById("usernames-wl").checked = false;
document.getElementById("usernames-bl").checked = false;
}
function changeState() {
const self = event.target
const parent = event.path[1]
if (self.type != "radio") {
document.getElementById("usernames-wl").checked = false;
document.getElementById("usernames-bl").checked = false;
}
console.log("usernames-wl is " + document.getElementById("usernames-wl").checked)
console.log("usernames-bl is " + document.getElementById("usernames-bl").checked)
}
<div id="usernames_buttons">
<input type="radio" name="usernames" id="usernames-bl" onclick="changeState()" checked/>
<label for="usernames-bl">BL</label>
<input type="radio" name="usernames" id="usernames-wl" onclick="changeState()"/>
<label for="usernames-wl">WL</label>
<button data-toggle onclick="changeState()">OFF</button>
</div>
The situation is that I have nine unique values for PayPal "add to cart" that I'm trying to place into a single HTML input tag, determined by the combination of choices from two sets of radio buttons (three radio buttons in each set).
The HTML could be slightly different, and the only reason it looks how it is now, is because I've been tinkering with various scripts trying to find a working method. The scripting could probably be much simpler, but I'd just like some help with understanding how to make it function (regardless of which radio buttons are changed, or how many times).
<form id="prod_size">
<input type="radio" name="size" value="1">small</input>
<input type="radio" name="size" value="4" checked="checked">medium</input>
<input type="radio" name="size" value="16">large</input>
</form>
<form id="prod_bundle">
<input type="radio" name="prod_bundle" value="single">single</input>
<input type="radio" name="prod_bundle" value="double">double</input>
<input type="radio" name="prod_bundle" value="triple" checked="checked">triple</input>
</form>
<form>
<input id="cart_button_value" value="green">
</form>
I don't see any errors in the browser console. Everything below is frankensteined from multiple code examples on stackoverflow/stackexchange, because I couldn't find a working solution by itself, unfortunately.
$("#prod_size , #prod_bundle").on('change', function() {
if ('#prod_size' == '1'){
if ("#prod_bundle".value == 'single'){
$("#cart_button_value").val = 'red';
}
else if ("#prod_bundle".value == 'double'){
$("#cart_button_value").val = 'green';
}
else if ("#prod_bundle".value == 'triple'){
$("#cart_button_value").val = 'blue';
}
}
else if ('#prod_size' == '4'){
if ("#prod_bundle".value == 'single'){
$("#cart_button_value").val = 'black';
}
else if ("#prod_bundle".value == 'double'){
$("#cart_button_value").val = 'white';
}
else if ("#prod_bundle".value == 'triple'){
$("#cart_button_value").val = 'gray';
}
}
else if ('#prod_size' == '16'){
if ("#prod_bundle".value == 'single'){
$("#cart_button_value").val = 'orange';
}
else if ("#prod_bundle".value == 'double'){
$("#cart_button_value").val = 'purple';
}
else if ("#prod_bundle".value == 'triple'){
$("#cart_button_value").val = 'pink';
}
}
}).trigger('change');
Your train of thought is somewhat on the right path, but there are number of errors in your code. For instance, "#prod_bundle".value is not a valid statement. The only reason why you are not seeing errors is because your first level if statements inside the "onChange" function will never evaluate to true, and thus the code inside them never runs. This is so because you are comparing two literal strings, and string:'#prod_size' == string:'1' can never equal one another.
At any rate, here's a way to go about it:
// comments are in reference to the code OP posted
// there is no need to fetch dom elements every time you need them
// store them in variables when the need to use them arises
var $prodSize = $('#prod_size')
var $prodBundle = $('#prod_bundle')
var $cartButton = $("#cart_button_value")
// creating a separate function to handle the change
// is not strictly necessary, but it makes things a bit cleaner
function handleOnChange() {
// find the selected size option and get its value
// size will contain "1", "4", or "16"
var size = $prodSize.children(':checked').val()
// find the selected bundle option and get its value
// bundle will contain "single", "double", or "triple"
var bundle = $prodBundle.children(':checked').val()
// create a value variable to grab the desired color
// to insert into the "cart button" input.
var value = ''
// make comparisons, similar to what you were doing
// except now we are using variables
if (size == 1){
if (bundle === 'single') value = 'red';
else if (bundle === 'double') value = 'green';
else if (bundle === 'triple') value = 'blue';
} else if (size == 4){
if (bundle === 'single') value = 'black';
else if (bundle === 'double') value = 'white';
else if (bundle === 'triple') value = 'gray';
} else if (size == 16){
if (bundle === 'single') value = 'orange';
else if (bundle === 'double') value = 'purple';
else if (bundle === 'triple') value = 'pink';
}
// update the cart button input with whatever color was picked
$cartButton.val(value)
}
// attach the on change events
$prodBundle.on('change', handleOnChange)
$prodSize.on('change', handleOnChange)
// trigger it for the first time
$prodSize.trigger('change')
<form id="prod_size">
<input type="radio" name="size" value="1">small</input>
<input type="radio" name="size" value="4" checked="checked">medium</input>
<input type="radio" name="size" value="16">large</input>
</form>
<form id="prod_bundle">
<input type="radio" name="prod_bundle" value="single">one</input>
<input type="radio" name="prod_bundle" value="double">two</input>
<input type="radio" name="prod_bundle" value="triple" checked="checked">three</input>
</form>
<form>
<input id="cart_button_value" value="green">
</form>
<script src="https://code.jquery.com/jquery-3.0.0.min.js" integrity="sha256-JmvOoLtYsmqlsWxa7mDSLMwa6dZ9rrIdtrrVYRnDRH0=" crossorigin="anonymous"></script>
I hope that helps.
I got another one:
Use data attributes to set the values that you want to show on the input, and then ask for them..
<form id="prod_size">
<input type="radio" name="size" value="one">small</input>
<input type="radio" name="size" value="four" checked="checked">medium</input>
<input type="radio" name="size" value="sixteen">large</input>
</form>
<form id="prod_bundle">
<input type="radio" name="prod_bundle" value="single" data-one="red" data-four="black" data-sixteen="orange">single</input>
<input type="radio" name="prod_bundle" value="double" data-one="green" data-four="white" data-sixteen="purple">double</input>
<input type="radio" name="prod_bundle" value="triple" data-one="blue" data-four="gray" data-sixteen="pink" checked="checked">triple</input>
</form>
<form>
<input input id="cart_button_value" value="green"/>
</form>
And the javascript function should be like this...
$(function(){
$('[name="size"]').change(changeInputVal);
$('[name="prod_bundle"]').change(changeInputVal);
function changeInputVal(){
var sizeSelected = $('input[name="size"]:checked', 'form#prod_size').val();
var valueToInput = $('input[name="prod_bundle"]:checked', 'form#prod_bundle').data(sizeSelected);
$("#cart_button_value").val(valueToInput);
}
});
I hope this could help you
I'm new to posting/stackoverflow, so please forgive me for any faux pas. I have multiple buttons and checkboxes that I need to store the values of to place into conditional statements.
The HTML code:
<h1>SECTION 1: GENDER</h1>
<p>What is your gender?</p>
<input type="button" onclick="storeGender(this.value)" value="Male"/>
<input type="button" onclick="storeGender(this.value)" value="Female"/>
<hr />
<h1>SECTION 2: AGE</h1>
<p>What is your age?</p>
<input type="button" onclick="storeAge(this.value)" value="18–22"/>
<input type="button" onclick="storeAge(this.value)" value="23–30"/>
<hr />
<h1>SECTION 3: TRAITS</h1>
<h3>Choose Two:</h3>
<form>
<input name="field" type="checkbox" value="1"/> Casual <br />
<input name="field" type="checkbox" value="10"/> Cheerful <br />
<input name="field" type="checkbox" value="100"/> Confident <br />
<input name="field" type="checkbox" value="1000"/> Tough <br />
<input type="button" id="storeTraits" value="SUBMIT" /> <br />
</form>
<hr />
<h2>Here is what I suggest</h2>
<p id="feedback">Feedback goes here.</p>
jQuery code:
// set up variables
var gender;
var age;
var string;
$(document).ready(function() {
startGame();
$("#storeTraits").click( function() {
serializeCheckbox();
}
); }
);
function startGame() {
document.getElementById("feedback").innerHTML = "Answer all the questions.";
}
function storeGender(value) {
gender = value;
}
function storeAge(value) {
age = value;
}
function serializeCheckbox() {
// clear out any previous selections
string = [ ];
var inputs = document.getElementsByTagName('input');
for( var i = 0; i < inputs.length; i++ ) {
if(inputs[i].type == "checkbox" && inputs[i].name == "field") {
if(inputs[i].checked == true) {
string.push(inputs[i].value);
}
}
}
checkFeedback();
}
//Limit number of checkbox selections
$(function(){
var max = 2;
var checkboxes = $('input[type="checkbox"]');
checkboxes.change(function(){
var current = checkboxes.filter(':checked').length;
checkboxes.filter(':not(:checked)').prop('disabled', current >= max);
});
});
function checkFeedback() {
if(gender == "Male") {
if (age == "18–22" && string == 11){
document.getElementById("feedback").innerHTML = "test1";
} else if (age == "18–22" && string == 110){
document.getElementById("feedback").innerHTML = "test2";
} else if (age == "18–22" && string == 1100){
document.getElementById("feedback").innerHTML = "test3";
} else if (age == "18–22" && string == 101){
document.getElementById("feedback").innerHTML = "test4";
}
}
}
I found this code on JSFiddle: http://jsfiddle.net/GNDAG/ which is what I want to do for adding together my trait values. However, when I try to incorporate it my conditional statements don't work. How do I add the code from the jsfiddle example and get the conditional statements to work? Thank you!
You need an integer, not a string array. Here's the code you need:
var traits = 0;
$('input[name=field]:checked').each(function () {
traits += parseInt($(this).val(), 10);
});
This will set the "traits" variable to an integer like 1, 11, 101, or 1001.
BTW: The second parameter to parseInt() is the base.
But a few suggestions:
Don't use "string" as a variable name.
Use radio buttons for gender and age.
Put all the input elements in the form.
Have one button that submits the form.
Attach a handler to the form submit event, and do your processing in that function, but call e.preventDefault() to prevent the form from submitting to the server. Alternatively, you could have the single button not be a submit button and attach an on-click handler to it.
Here's a jsfiddle with the code above and all the suggestions implemented.
In my view model I have a IsMale value that has the value true or false.
In my UI I wish to bind it to the following radio buttons:
<label>Male
<input type="radio" name="IsMale" value="true" data-bind="checked:IsMale"/>
</label>
<label>Female
<input type="radio" name="IsMale" value="false" data-bind="checked:IsMale"/>
</label>
The problem I think is checked expects a string "true" / "false". So my question is, how can I get this 2-way binding w/ this UI and model?
I know this is an old thread, but I was having the same problem and found out a much better solution that was probably added to knockout after this question was officially answered, so I'll just leave it for people with the same problem.
Currently there is no need for extenders, custom binding handlers or computeds.
Just provide a "checkedValue" option, it will use that instead of the html 'value' attribute, and with that you can pass any javascript value.
<input type="radio" name="a" data-bind="checked:IsChecked, checkedValue: true"/>
<input type="radio" name="a" data-bind="checked:IsChecked, checkedValue: false"/>
Or:
<input type="radio" name="b" data-bind="checked:Quantity, checkedValue: 1"/>
<input type="radio" name="b" data-bind="checked:Quantity, checkedValue: 2"/>
<input type="radio" name="b" data-bind="checked:Quantity, checkedValue: 3"/>
One option is to use a writeable computed observable.
In this case, I think that a nice option is to make the writeable computed observable a "sub-observable" of your IsMale observable. Your view model would look like:
var ViewModel = function() {
this.IsMale = ko.observable(true);
this.IsMale.ForEditing = ko.computed({
read: function() {
return this.IsMale().toString();
},
write: function(newValue) {
this.IsMale(newValue === "true");
},
owner: this
});
};
You would bind it in your UI like:
<label>Male
<input type="radio" name="IsMale" value="true" data-bind="checked:IsMale.ForEditing"/>
</label>
<label>Female
<input type="radio" name="IsMale" value="false" data-bind="checked:IsMale.ForEditing"/>
</label>
Sample: http://jsfiddle.net/rniemeyer/Pjdse/
This works for me:
http://jsfiddle.net/zrBuL/291/
<label>Male
<input type="radio" name="IsMale" value="1" data-bind="checked:IsMale"/>
</label>
<label>Female
<input type="radio" name="IsMale" value="0" data-bind="checked:IsMale"/>
</label>
ko.bindingHandlers['radiobuttonyesno'] = {
'init': function (element, valueAccessor, allBindingsAccessor) {
var stateHandler = function (property, allBindingsAccessor, key, value, checkIfDifferent) {
if (!property || !ko.isObservable(property)) {
var propWriters = allBindingsAccessor()['_ko_property_writers'];
if (propWriters && propWriters[key])
propWriters[key](value);
} else if (ko.isWriteableObservable(property) && (!checkIfDifferent || property.peek() !== value)) {
property(value);
}
};
var updateHandler = function () {
var valueToWrite;
if ((element.type == "radio") && (element.checked)) {
valueToWrite = element.value;
} else {
return; // "radiobuttonyesno" binding only responds to selected radio buttons
}
valueToWrite = (valueToWrite === "True") ? true : false;
var modelValue = valueAccessor(), unwrappedValue = ko.utils.unwrapObservable(modelValue); //can be true of false
stateHandler(modelValue, allBindingsAccessor, 'checked', valueToWrite, true);
};
ko.utils.registerEventHandler(element, "click", updateHandler);
// IE 6 won't allow radio buttons to be selected unless they have a name
if ((element.type == "radio") && !element.name)
ko.bindingHandlers['uniqueName']['init'](element, function () { return true });
},
'update': function (element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
value = value ? "True" : "False";
if (element.type == "radio") {
element.checked = (element.value == value);
}
}
};
Use this binder instead of creating stupid ko computed observables.
Example:
<label>Male
<input type="radio" name="IsMale" value="True" data-bind="radiobuttonyesno:IsMale"/>
</label>
<label>Female
<input type="radio" name="IsMale" value="False" data-bind="radiobuttonyesno:IsMale"/>
</label>
Once you figure out that the initial match for the radio button wants to match only a string and wants to set the value to a string, it is simply a matter of converting your initial value to string. I had to fight this with Int values.
After you have setup your observables, convert the value to string and KO will do its magic from there. If you are mapping with individual lines, do the conversion in those lines.
In the example code, I'm using Json to map the whole Model in a single command.
Then letting Razor insert the value between the quotes for the conversion.
script type="text/javascript">
KoSetup.ViewModel = ko.mapping.fromJS(#Html.Raw(Json.Encode(Model)));
KoSetup.ViewModel.ManifestEntered("#Model.ManifestEntered"); //Bool
KoSetup.ViewModel.OrderStatusID("#Model.OrderStatusID"); //Int
</script>
I use a "Dump it all to the screen" at the bottom of my web page during development.
<h4>Debug</h4>
<pre data-bind="text: ko.toJSON($data, null, 2)"></pre>
Here are the data values, Before
"OrderStatusID": 6,
"ManifestEntered": true,
and, After
"OrderStatusID": "6",
"ManifestEntered": "True",
In my project, I didn't need to convert Bools, because I'm able to use a checkbox that doesn't have the same frustration.
Why not simply true and false instead of 1 and 0?
<label>Male
<input type="radio" name="IsMale" value="true" data-bind="checked:IsMale"/>
</label>
<label>Female
<input type="radio" name="IsMale" value="false" data-bind="checked:IsMale"/>
</label>
You can also use an extender so it's easy to reuse them for more observables:
ko.extenders.boolForEditing = function (target, allowNull) {
var result = ko.computed({
read: function () {
var current = target();
var newValue = null;
if (current === undefined || current === null || current === '') {
if (!allowNull) {
newValue = 'false';
}
} else {
newValue = current ? 'true' : 'false';
}
return newValue;
},
write: function (newValue) {
var current = target();
var valueToWrite = null;
if (newValue === undefined || newValue === null || newValue === '') {
if (!allowNull) {
valueToWrite = false;
}
} else {
valueToWrite = newValue === 'true';
}
// only write if it changed
if (valueToWrite !== current) {
target(valueToWrite);
} else {
if (newValue !== current) {
target.notifySubscribers(valueToWrite);
}
}
}
}).extend({
notify: 'always'
});
result(target());
return result;
};
Then use it like this:
this.IsMale.forEditing = this.IsMale.extend({boolForEditing: true});
The parameter provided to boolForEditing indicates whether the value may be null.
See http://jsfiddle.net/G8qs9/1/
After doing lot of research for older version of knockout prior to 3.0 there are possibly two best options
Create a knockout extender like
ko.extenders["booleanValue"] = function (target) {
target.formattedValue = ko.computed({
read: function () {
if (target() === true) return "True";
else if (target() === false) return "False";
},
write: function (newValue) {
if (newValue) {
if (newValue === "False") target(false);
else if (newValue === "True") target(true);
}
}
});
target.formattedValue(target());
return target;
};
To use the extender on your model, you’d do something like the following:
function Order() {
this.wantsFries= ko.observable(false).extend({ booleanValue: null });
}
<span>Do you want fries with that?</span>
<label>
<input type="radio" name="question" value="True"
data-bind="value: wantsFries.formattedValue" /> Yes
</label>
<label>
<input type="radio" name="question" value="False"
data-bind="value: wantsFries.formattedValue" /> No
</label>
source:http://www.timlabonne.com/2013/02/building-a-knockout-js-extender-for-boolean-values/