I'm producing a list of radio buttons that's looking at a list of items containing individual countries and associated regions. Below is the XSL for my radio buttons
<xsl:template match="/">
<div id="filter">
<xsl:call-template name="container" />
</div>
</xsl:template>
<xsl:template name="container">
<xsl:variable name="Rows" select="/dsQueryResponse/Rows/Row"/>
<xsl:for-each select="$Rows">
<xsl:call-template name="group-items"/>
</xsl:for-each>
</xsl:template>
<xsl:template name="group-items">
<label class="region-filter-item" region="{#Region}">
<input type="radio" name="region" class="regionbox">
<xsl:value-of select="#Region"/>
</input>
</label>
This produces the correct data, but it also duplicates many of the regions because if there are 15 countries in one region, that one region will be displayed 15 times.
What's the best way to only show each region once?
I wrote a JavaScript function that pushes each unique item into an array, and then use the array to populate my container. All resolved. Thanks for all the help guys:)
function removeDuplicates(){
var Array = new Array();
$('#filter > .filter-item').each(function(){
var country = $(this).attr('country ');
if ( $.inArray(region, Array ) == -1 ) {
Array .push(region);
}
});
Array .sort();
var length = Array .length;
for (var i = 0; i < length; i++) {
$('#filter-container').find('.container').append('<label class="filter-item" country="' + Array [i] + '">'
+ '<input type="radio" name="country" class="checkbox">'
+ Array [i] +
'</input>' +
'</label> ');
}
}
Related
I have a div as follows:
<div class="questionholder" id="question5" style="display:none">
<div>
<h5>Select all that apply</h5>
<input class="input5" type="checkbox" id="ID1elementColor" name="ID1element" value="color"><label for="ID1elementColor"><p class="radioChoice">Color</p></label>
<input class="input5" type="checkbox" id="ID1elementHeight" name="ID1element" value="height"><label for="ID1elementHeight"><p class="radioChoice">Height</p></label>
<input class="input5" type="checkbox" id="ID1elementWeight" name="ID1element" value="weight"><label for="ID1elementWeight"><p class="radioChoice">Weight</p></label>
</div>
</div>
<div class="holdButtons">
<a class="text2button" onclick="displayquestion(6);">Next</a>
</div>
The user is expected to select all the checkboxes that apply to his situation. Let's assume he selects all 3.
When he clicks "Next", the function displayquestion(); will fire.
function displayquestion(a) {
var Elements = '';
var b = a - 1;
Elements = document.querySelector("#question" + b + " input[name=ID1element]").value;
}
Basically, the function is meant to store all the checked values into var Elements, which is meant to be an array.
However, I'm only getting the value of the first selected answer instead of an array of all selected answers.
How do I grab all the selected answers into an array?
No jQuery please.
Use querySelectorAll to get an array-like NodeList instead of querySelector, and then you can use Array.from to transform that NodeList into an array containing only the .value of the selected inputs:
function displayquestion(a) {
const b = a - 1;
const elements = Array.from(
document.querySelectorAll('#question' + b + ' input:checked'),
input => input.value
);
console.log(elements);
}
<div class="questionholder" id="question5">
<div>
<h5>Select all that apply</h5>
<input class="input5" type="checkbox" id="ID1elementColor" name="ID1element" value="color"><label for="ID1elementColor"><p class="radioChoice">Color</p></label>
<input class="input5" type="checkbox" id="ID1elementHeight" name="ID1element" value="height"><label for="ID1elementHeight"><p class="radioChoice">Height</p></label>
<input class="input5" type="checkbox" id="ID1elementWeight" name="ID1element" value="weight"><label for="ID1elementWeight"><p class="radioChoice">Weight</p></label>
</div>
</div>
<div class="holdButtons">
<a class="text2button" onclick="displayquestion(6);">Next</a>
</div>
Here is the script that you can use for that:
I haven't changed anything in your HTML structure. Except I have removed the display: none; from the style attribute of the class questionholder.
<script>
function displayquestion(b) {
let checkboxList = document.querySelectorAll("#question" + b + " input:checked");
let obj = [];
if (checkboxList.length > 0) { //Code works only if some checbox is checked
checkboxList.forEach(function(item) {
obj.push(item.value); //Contains the value of all the selected checkboxes.
});
}
console.log(obj); //array list containing all the selected values
}
</script>
<div class="questionholder" id="question5" style="">
<div>
<h5>Select all that apply</h5>
<input class="input5" type="checkbox" id="ID1elementColor" name="ID1element" value="color"><label for="ID1elementColor"><p class="radioChoice">Color</p></label>
<input class="input5" type="checkbox" id="ID1elementHeight" name="ID1element" value="height"><label for="ID1elementHeight"><p class="radioChoice">Height</p></label>
<input class="input5" type="checkbox" id="ID1elementWeight" name="ID1element" value="weight"><label for="ID1elementWeight"><p class="radioChoice">Weight</p></label>
</div>
</div>
<div class="holdButtons">
<a class="text2button" onclick="displayquestion(5);">Next</a>
</div>
Here is a JSFiddle link for that.
I hope this is helpful.
So first of I would make a variable for your
<a class="text2button">Next</a>. And I have removed the
onclick="displayquestion(6)" from your html.
Here is the variable.
var text2button = document.getElementsByClassName("text2button")[0];
text2button.addEventListener("click", displayquestion);
Here we have the function, so what I've done is.
I have created a variable var elements = []; Which is a empty array.
Then I create this variable var inputs = document.getElementsByClassName("input5");
This variable gets all the inputs with class input5.
Next I would loop through each of the inputs from the var inputs. Like this.
for (var i = 0; i < inputs.length; i++) {
if (inputs[i].checked) {
elements.push(inputs[i].value);
}
}
So what I do here is loop through each input for (var i = 0; i < inputs.length; i++) and then I check if any of the inputs are checked if (inputs[i].checked), then I push them to the array var elements with elements.push(inputs[i].value);.
And then I use console.log(elements); so show it in the console.
Check out the snippet below to see it in effect.
Hope this helps.
var text2button = document.getElementsByClassName("text2button")[0];
text2button.addEventListener("click", displayquestion);
function displayquestion() {
var elements = [];
var inputs = document.getElementsByClassName("input5");
for (var i = 0; i < inputs.length; i++) {
if (inputs[i].checked) {
elements.push(inputs[i].value);
}
}
console.log(elements);
}
<div class="questionholder" id="question5">
<div>
<h5>Select all that apply</h5>
<input class="input5" type="checkbox" id="ID1elementColor" name="ID1element" value="color"><label for="ID1elementColor"><p class="radioChoice">Color</p></label>
<input class="input5" type="checkbox" id="ID1elementHeight" name="ID1element" value="height"><label for="ID1elementHeight"><p class="radioChoice">Height</p></label>
<input class="input5" type="checkbox" id="ID1elementWeight" name="ID1element" value="weight"><label for="ID1elementWeight"><p class="radioChoice">Weight</p></label>
</div>
</div>
<div class="holdButtons">
<a class="text2button">Next</a>
</div>
I had finished filtering Series dropdown with the application dropdown. What I want now is to filter the results of the first filtering using the case size dropdown.
Here is the code of the dropdown:
<select name="series" onchange="changeCalc()" id="idCalcSelect" class="CalcSelect">
<option selected="1" style="display:none;">Series</option>
<xsl:for-each select="//calc">
<xsl:sort select="#series" order="ascending" data-type="text"/>
<option>
<xsl:choose>
<xsl:when test="#series[contains(substring(.,13,2),'A')]">
<xsl:attribute name="app">Automotive</xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="app">Commercial</xsl:attribute>
</xsl:otherwise>
</xsl:choose>
<xsl:attribute name="style">display: normal;</xsl:attribute>
<xsl:attribute name="value"><xsl:value-of select="#calc-id"/></xsl:attribute>
<xsl:attribute name="caseSize"><xsl:value-of select="substring(#series,1,9)"/></xsl:attribute>
<xsl:variable name="series" select="#series"/>
<xsl:value-of select="substring($series,10,5)"/>
</option>
</xsl:for-each>
<option id="noSeries" style="display: none;">NO SERIES AVAILABLE</option>
</select>
What should I add with my script, see my code below:
var selectedApp = "Automotive";
jq("#selectApp").on("change", function() {
selectedApp = jq(this).find('option:selected').text();
jq("select[name='series'] > option").each(function() {
var attrApp = jq(this).attr("app");
if (selectedApp == attrApp) {
this.show();
} else {
this.hide();
}
});
});
var selectedCS;
jq("#selectCaseSize").on("change", function() {
selectedCS = jq(this).find('option:selected').text();
jq("select[name='series'] > option").each(function() {
var attrCS = jq(this).attr("caseSize");
if (selectedCS == attrCS) {
this.show();
} else {
this.hide();
}
});
});
So what I want here is to filter the results of the first filtering. Whether if you use the case size dropdown first or the application dropdown first.
EDIT: I need to filter them using the attributes.
I creating a dropdown multiple checkbox filter function for my gantt chart, but I'm having trouble getting all selected value and append it into an array. can anyone help me with this, any help is much appreciated
Below is my code :
HTML :
<label class="text-primary" for="type_2">Search Type: </label>
<dl id="type_2" class="dropdown">
<dt>
<a href="#">
<span class="hida">ALL</span>
<p class="multiSel"></p>
</a>
</dt>
<dd>
<div class="search_type_filter">
<ul>
<li><input type="checkbox" value="ALL" selected="Selected" checked="1" />ALL</li>
<li><input type="checkbox" value="Car" />Car</li>
<li><input type="checkbox" value="Bike"/>Bike</li>
<li><input type="checkbox" value="Ball"/>Ball</li>
</ul>
</div>
</dd>
</dl>
Javascript :
$('.search_type_filter input[type="checkbox"]').on('click', function() {
var title = $(this).closest('.search_type_filter').find('input[type="checkbox"]').val(),
title = $(this).val() + ",";
var values = $(this).closest('.search_type_filter').find('input[type="checkbox"]').val(),
values = $(this).val();
search_type_value = {};// put combo value into scope variable
for(var i = 0; i < values.length; i++){
search_type_value[values[i]] = true;// build hash for easy check later
}
console.log(search_type_value);
gantt.render();// and repaint gantt
if ($(this).is(':checked')) {
var html = '<span title="' + title + '">' + title + '</span>';
$('.multiSel').append(html);
$(".hida").hide();
} else {
$('span[title="' + title + '"]').remove();
var ret = $(".hida");
$('.dropdown dt a').append(ret);
}
});
gantt.attachEvent("onBeforeTaskDisplay", function (id, task) {
if(search_type_value['ALL'])
return true;
return !!search_type_value[task.search_type];
});
So the end result what I want is let say I check Car and Ball it will give me an array like this :
{Car: true, Ball: true}
but with this I'm getting by letter and its getting only one value :
{C: true, a: true, r: true}
Here is an example. I added comments that explain whats going on in the code but essentially you just want to create a JSON array based on the checkbox elements on your form.
I also included an alternative to this that uses multi-dimensional arrays but I highly recommend you go down the JSON path instead.
//on button click
$("#click").click(function()
{
//create variable to hold the array
var yourArray = [];
//for each checkbox within the group
$("input[name='group']").each(function()
{
//return if its checked or not
var isChecked = $(this).is(":checked");
//get the value of the checkbox i.e. Bike etc.
var value = $(this).val();
//Create a new object using above variables
var myObject = new Object();
myObject.value = value;
myObject.isChecked = isChecked;
//push the object onto the array
yourArray.push(myObject);
});
//Now you have a dynamic object you can use to select what you need
console.log("Using JSON Array (recommended)");
console.log(yourArray[0].value);
console.log(yourArray[0].isChecked);
console.log(yourArray[1].value);
console.log(yourArray[2].value);
//showing everything in the array
console.log(yourArray);
//if you really need to have the output as Ball:true, Bike:false etc you can break up the array you already have like this:
//Create 2d array
var multiArray = [];
//foreach index in your json array
$.each(yourArray, function(key, value)
{
//create a new array
var newArray = [];
//push the values into it
newArray.push(value.value);
newArray.push(value.isChecked);
//push the array onto the 2d array
multiArray.push(newArray);
});
//output the results
console.log("Using 2D Array");
console.log(multiArray);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label class="text-primary" for="type_2">Search Type: </label>
<dl id="type_2" class="dropdown">
<dt>
<a href="#">
<span class="hida">ALL</span>
<p class="multiSel"></p>
</a>
</dt>
<dd>
<div class="search_type_filter">
<ul>
<li><input type="checkbox" name="group" value="ALL" selected="Selected" checked="1" />ALL</li>
<li><input type="checkbox" name="group" value="Car" />Car</li>
<li><input type="checkbox" name="group" value="Bike" />Bike</li>
<li><input type="checkbox" name="group" value="Ball" />Ball</li>
</ul>
</div>
</dd>
</dl>
<button type="button" id="click"> check </button>
I am trying to create a javascript code for my website to do the calculations once a checkbox is checked. Each time i select a checkbox it should calculate the total price of the items.
This is my html code:
<form id="orderForm" action="#" method="get">
<section id="selectBook">
<h2>Select books</h2>
<?php
include_once('database_conn.php');
$sqlBooks = 'SELECT bookISBN, bookTitle, bookYear, catDesc, bookPrice FROM nbc_book b inner join nbc_category c on b.catID = c.catID WHERE 1 order by bookTitle';
$rsBooks = mysqli_query($conn, $sqlBooks);
while ($book = mysqli_fetch_assoc($rsBooks)) {
echo "\t<div class='item'>
<span class='bookTitle'>{$book['bookTitle']}</span>
<span class='bookYear'>{$book['bookYear']}</span>
<span class='catDesc'>{$book['catDesc']}</span>
<span class='bookPrice'>{$book['bookPrice']}</span>
<span class='chosen'><input type='checkbox' name='book[]' value='{$book['bookISBN']}' title='{$book['bookPrice']}' /></span>
</div>\n";
}
?>
</section>
<section id="collection">
<h2>Collection method</h2>
<p>Please select whether you want your chosen book(s) to be delivered to your home address (a charge applies for this) or whether you want to collect them yourself.</p>
<p>
Home address - £3.99 <input type="radio" name="deliveryType" value="home" title="3.99" checked = "checked" /> |
Collect from warehouse - no charge <input type="radio" name="deliveryType" value="trade" title="0" />
</p>
</section>
<section id="checkCost">
<h2>Total cost</h2>
Total <input type="text" name="total" id="total" size="10" readonly="readonly" />
</section>
The code has been separated into tag.
This is my current javascript code which i have written:
var item = document.getElementsByClassName("item");
var chkbox = document.getElementsByTagName("input");
for(var i = 0; i < chkbox.length; i++){
chkbox[i].onchange = function(){
//Recalculate total
getTotal();
}
}
function getTotal(){
var total = 0.0;
for(var i = 1; i <= chkbox.length; i++){
//If the checkbox is checked, add it to the total
if(chkbox[i-1].checked){
total = total + parseFloat(chkbox[i].value);
}
}
return total;
document.getElementById("total").innerHTML = total;
}
I really need some experts to help me on this. Thank you.
In getTotal() you are returning before setting the value here:
return total;
document.getElementById("total").innerHTML = total;
Set the input with the value rather than innerHTHML.
document.getElementById("total").setAttribute("value", total);
I had to change the checked to be parseFloat(chkbox[i-1].title) to match the if statement
jsFiddle
The above example uses to products, the first priced at 1 and the second at 2.
I'm trying to use a template that appends white space to a string.
<xsl:call-template name="append-pad">
<xsl:with-param name="padChar" select="' '" />
<xsl:with-param name="padVar" select="$value" />
<xsl:with-param name="length" select="15" />
</xsl:call-template>
<xsl:template name="append-pad">
<!-- recursive template to left justify and append -->
<!-- the value with whatever padChar is passed in -->
<xsl:param name="padChar" />
<xsl:param name="padVar" />
<xsl:param name="length" />
<xsl:choose>
<xsl:when test="string-length($padVar) < $length">
<xsl:call-template name="append-pad">
<xsl:with-param name="padChar" select="$padChar" />
<xsl:with-param name="padVar" select="concat($padVar,$padChar)" />
<xsl:with-param name="length" select="$length" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="substring($padVar,1,$length)" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
But the length of the with space is dynamic. This is what I tried in javascript but I get an error saying 'NAME cannot begin with '' when trying to debug the xslt.
function firstName(name) {
try {
var n = name.toString;
var target = name.length - 20;
var whiteString = "";
for ( i = 0; i < target; i++) {
whiteString.concat(" ");
}
n = n + whiteString;
return n;
} catch(err) {
return " ";
}
}
How can I do this logic in xslt?
<xsl:value-of select="concat(substring(' ', string-length() +1), $firstName)"/>
If, from your JavaScript example, you always want to pad the string up to a maximum of 20 characters, then you can simply use:
<xsl:value-of select="concat(substring(' ', string-length($firstName) +1), $firstName)" />
How does this work?
First take the expression: substring(' ', string-length($firstName) +1)
This will take the string of 20 spaces, and return a string of spaces that is 20 - length of $firstName as we are using substring to only extract a portion of the string.
We then use the concat function to join the two together. We put the substring of spaces first to pad left (although we could always put them second if you wanted to pad right).
In select you have to use an expression.
To set constant values in your param do this
<xsl:with-param name="padChar"> </xsl:with-param>
<xsl:with-param name="length">15</xsl:with-param>