Match values of radio button selections to array - javascript

I have a few radio button groups, depending on which radio button is selected in each group, that particular answer needs to return 1 or more values which are preset in an array.
So, if 1 is selected in group 1, A & B values both increment by 1, If 2 is selected B, C & D increment and so on. At the end the letter with most points/increments should be returned (when the form is submitted)
How can I get going with this? I think the starting point is to return the selected radio buttons, match them to the correct array index, then check for the values in that array (letters) with the most increments and return it's value(s)?
$(function(){
var group1 = new Array();
group1[0] = "A, B";
group1[1] = "B, C, D";
group1[2] = "E, B";
group1[3] = "B";
group1[4] = "F";
var group2 = new Array();
group2[0] = "D, A";
group2[1] = "D, C";
group2[2] = "B, F, E";
group2[3] = "A";
group2[4] = "B, D";
$('form').submit(function(){
var checked = $('input:radio:checked').length;
//This is as far as I am
});
});
<form>
<input type="radio" name="group1" value="1" id="q1-1" /> 1
<input type="radio" name="group1" value="2" id="q1-2" /> 2
<input type="radio" name="group1" value="3" id="q1-3" /> 3
<input type="radio" name="group1" value="4" id="q1-4" /> 4
<input type="radio" name="group1" value="5" id="q1-5" /> 5
<br /><br />
<input type="radio" name="group2" value="1" id="q2-1" /> 1
<input type="radio" name="group2" value="2" id="q2-2" /> 2
<input type="radio" name="group2" value="3" id="q2-3" /> 3
<input type="radio" name="group2" value="4" id="q2-4" /> 4
<input type="radio" name="group2" value="5" id="q2-5" /> 5
<input type="submit" value="submit" />
</form>

Check with it will give you result as you created array so i used switch to select the values from array.
var temp=0;
var result = [];
var maxvalue = 0;
var topQualityjob = "";
$('input:radio:checked').each(function () {
switch ($(this).attr("name")) {
case "group1":
$(group1[parseInt($(this).val()) - 1].split(",")).each(function () {
result.push(this);
temp = getaccurance(result, this);
if (maxvalue < temp) {
maxvalue = temp;
topQualityjob = this;
}
});
break;
case "group2":
$(group2[parseInt($(this).val()) - 1].split(",")).each(function () {
result.push(this);
temp = getaccurance(result, this);
if (maxvalue < temp) {
maxvalue = temp;
topQualityjob = this;
}
});
break;
}
});
alert(topQualityjob);
}
function getaccurance(result, val) {
num = 0;
for (i = 0; i < result.length; i++) {
if (result[i] == val)
num++;
}
return num;
}
Hope this will give correct answer

Related

How to show values from a .js file previously executed from a webpage to another webpage?

This is the webpage that will execute calculations in JS there are other personalityType I just didn't include them
<div class="question">
<div>40. It is easy for me to identify how I feel and why. </div>
<div> <input class="radiobutton" type="radio" name="m40" value="0" personalityType="intrapersonal"> Never <input class="radiobutton" type="radio" name="m40" value="1" personalityType="intrapersonal"> Rarely <input
class="radiobutton" type="radio" name="m40" value="2" personalityType="intrapersonal"> Often
<input class="radiobutton" type="radio" name="m40" value="3" personalityType="intrapersonal"> Always
</div>
<div class="question">
<div>35. English is/was one of my favorite subjects in school. </div>
<div> <input class="radiobutton" type="radio" name="m35" value="0" personalityType="verbal"> Never <input class="radiobutton" type="radio" name="m35" value="1" personalityType="verbal"> Rarely <input class="radiobutton"
type="radio" name="m35" value="2" personalityType="verbal">
Often
<input class="radiobutton" type="radio" name="m35" value="3" personalityType="verbal"> Always
</div>
<div>
<a class="myButton" onclick=calculateScores() href=results.html>Get Results</a>
</div>
This is the .js
var bodilyScore = 0;
var mathematicalScore = 0;
var naturalistScore = 0;
var interpersonalScore = 0;
var visualScore = 0;
var verbalScore = 0;
var intrapersonalScore = 0;
var musicalScore = 0;
function calculateScores() {
var button = document.getElementsByClassName("radiobutton");
var buttonLength = button.length;
musicalScore = 0;
bodilyScore = 0;
mathematicalScore = 0;
naturalistScore = 0;
interpersonalScore = 0;
visualScore = 0;
verbalScore = 0;
intrapersonalScore = 0;
for (var i = 0; i < buttonLength; i++) {
if (button[i].type === 'radio' && button[i].checked) {
var value = Number(button[i].value);
var type = button[i].getAttribute("personalityType");
switch (type) {
case "musical":
musicalScore += value;
break;
case "bodily":
bodilyScore += value;
break;
case "mathematical":
mathematicalScore += value;
break;
case "naturalist":
naturalistScore += value;
break;
case "interpersonal":
interpersonalScore += value;
break;
case "visual":
visualScore += value;
break;
case "verbal":
verbalScore += value;
break;
case "intrapersonal":
intrapersonalScore += value;
break;
}
}
}
showResults();
}
function showResults() {
console.log(musicalScore);
console.log(bodilyScore);
console.log(mathematicalScore);
console.log(naturalistScore);
console.log(interpersonalScore);
console.log(visualScore);
console.log(verbalScore);
console.log(intrapersonalScore);
document.getElementById('musicalResult').innerText = musicalScore;
document.getElementById('bodilyResult').innerText = bodilyScore;
document.getElementById('naturalistResult').innerText = naturalistScore;
document.getElementById('interpersonalResult').innerText = interpersonalScore;
document.getElementById('visualResult').innerText = visualScore;
document.getElementById('intrapersonalResult').innerText = intrapersonalScore;
document.getElementById('verbalResult').innerText = verbalScore;
document.getElementById('mathematicalResult').innerText = mathematicalScore;
}
I wanted to get the value of the 3 highest scores among musicalScore, verbalScore, etc.). after clicking the "Get Results" button and display it on another webpage. How could I also attach a text to the Score with the highest value to be displayed also?
If you want to pass your result to another page you can store them in LocalStorage.
highestResults = {mathematicalScore: 4, naturalistScore: 6, verbalScore: 5};
localStorage.setItem('calculationResults', highestResults);
And on result page.
localStorage.getItem('calculationResults');
If you want to add text to highest result:
document.getElementById('mathematicalResult').innerText = mathematicalScore + ' - highest result';

Assigning value to form input by "id” and not by “value” attribute

This is my current situation:
document.body.addEventListener('click', calculateTotal);
const calculator = document.querySelector("form");
function cake() {
const cakes = Array.from(calculator.elements["cake"]).slice(0, 3);
const raphael = calculator.elements["raphael"];
function isChecked(checkbox) {
return checkbox.checked;
}
var count = cakes.filter(isChecked).length;
if (count) {
count = count * 0.5 + 0.5;
}
if (raphael.checked) {
count += 1;
}
return count;
}
function occasion() {
const occasionOptions = {
birthday: 25,
anniversary: 50,
wedding: 100
}
var occasionCost = 0;
const occasion = calculator.elements["occasion"];
for (var i = 0; i < occasion.length; i++) {
if (occasion[i].checked) {
occasionCost = occasionOptions[occasion[i].value];
break;
}
}
return occasionCost;
}
function calculateTotal() {
var totalCost = cake() * occasion();
calculator.total.value = "$" + totalCost.toLocaleString("en");
}
<form>
<fieldset>
<legend>Select Cakes</legend>
<label><input type="checkbox" name="cake" id="leonardo" required>Leonardo</label>
<label><input type="checkbox" name="cake" id="donatello">Donatello</label>
<label><input type="checkbox" name="cake" id="michelangelo">Michelangelo</label>
<label><input type="checkbox" name="cake" id="raphael">Raphael</label>
<p>If you select more than one cake, the other cakes are discounted 50%.</p>
<p><small>Does not apply to Raphael.</small></p>
</fieldset>
<fieldset>
<legend>Choose Occasion</legend>
<label><input type="radio" name="occasion" value="birthday">Birthday</label>
<label><input type="radio" name="occasion" value="anniversary">Anniversary</label>
<label><input type="radio" name="occasion" value="wedding">Wedding</label>
</fieldset>
<input type="text" name="total">
</form>
In the example above, I would like to switch value to id attribute on input radio. If I for example replace value="birthday" to id="birthday", the values are no longer assigned to input.
What am I missing? Any help would be greatly appreciated.
(Code snippet updated to include both id and value in fieldsets.)
You can use HTMLElement.id to get the id of an element.
document.body.addEventListener('click', calculateTotal);
const calculator = document.querySelector("form");
function occasion() {
const occasionOptions = {
birthday: 2.5,
anniversary: 5,
wedding: 10
}
var occasionCost = 0;
const occasion = calculator.elements["occasion"];
for (var i = 0; i < occasion.length; i++) {
if (occasion[i].checked) {
occasionCost = occasionOptions[occasion[i].id];
break;
}
}
return occasionCost;
}
function calculateTotal() {
var totalCost = 100 * occasion();
calculator.total.value = "$" + totalCost.toLocaleString("en");
}
<form>
<fieldset>
<legend>Choose Occasion</legend>
<label><input type="radio" name="occasion" id="birthday">Birthday</label>
<label><input type="radio" name="occasion" id="anniversary">Anniversary</label>
<label><input type="radio" name="occasion" id="wedding">Wedding</label>
</fieldset>
<input type="text" name="total">
</form>
i do not know the rationale for using id property over value, but if that is what you want to do, all you need to do is to update your js to read id property instead of value property.
https://codepen.io/anon/pen/XBvYoL
HTML:
<form>
<fieldset>
<legend>Choose Occasion</legend>
<label><input type="radio" name="occasion" id="birthday">Birthday</label>
<label><input type="radio" name="occasion" id="anniversary">Anniversary</label>
<label><input type="radio" name="occasion" id="wedding">Wedding</label>
</fieldset>
<input type="text" name="total">
</form>
JS:
document.body.addEventListener('click', calculateTotal);
const calculator = document.querySelector("form");
function occasion() {
const occasionOptions = {
birthday: 2.5,
anniversary: 5,
wedding: 10
}
var occasionCost = 0;
const occasion = calculator.elements["occasion"];
for (var i = 0; i < occasion.length; i++) {
if (occasion[i].checked) {
occasionCost = occasionOptions[occasion[i].id];
break;
}
}
return occasionCost;
}
function calculateTotal() {
var totalCost = 100 * occasion();
calculator.total.value = "$" + totalCost.toLocaleString("en");
}

HTML form with javascript gets "NaN" in IE but works in Chrome

I am by no means a programmer but I managed to get this to work in Chrome but I get "NaN" when I try it on IE (11 if that matters).
It basically takes 4 criteria and does some math to give a price quote.Can anyone help with this?
<html>
<head>
<title>instant inspection quote tool</title>
<SCRIPT Language="JavaScript">
function calculateFee(frm){
var building = frm.building.value
var distance = frm.distance.value
var age = frm.age.value
var sqft = frm.sqft.value
var total = 0
building = Number(building)
distance = Number(distance)
age = Number(age)
sqft = Number(sqft)
total = Number(total)
total = building + distance + age + sqft
frm.total.value = total
}
</script>
</head>
<body>
<h1>Inspection Fee Calculator</h1>
<form method="post" action="">
Select the type of home
<br><input type="radio" name="building" value="375"> detached
<br><input type="radio" name="building" value="350"> semi-detached
<br><input type="radio" name="building" value="350"> condo or freehold townhome - end unit
<br><input type="radio" name="building" value="325"> condo or freehold townhome - interior unit
<br><input type="radio" name="building" value="299"> condo apartment
<br><br>Is the home within 50 kms of Ottawa?
<br><input type="radio" name="distance" value="0"> yes
<br><input type="radio" name="distance" value="25"> no
<br><br>Is the home less than 50 years old?
<br><input type="radio" name="age" value="0"> yes
<br><input type="radio" name="age" value="25"> no
<br><br>Is the home less than 2000 square feet?
<br><input type="radio" name="sqft" value="0"> yes
<br><input type="radio" name="sqft" value="25"> no
<br><br>
<input type="button" name="button" value="Calculate Fee" onClick="calculateFee(this.form)">
<table>
<tr>
<td align="right">Total Inspection fee:</td>
<td>
<input type="text" name="total" size="30" maxlength="30">
</td>
</tr>
</table>
</form>
</body>
</html>
Try this - note: querySelector and querySelectorAll do not work in IE < 8 and in 8 only in standards mode
Live Demo
function calculateFee(frm) {
var total = 0,
rads = frm.querySelectorAll('input:checked'); // get all checked radios
for (var i = 0; i < rads.length; i++) {
var num = Number(rads[i].value);
total += isNaN(num) ? 0 : num;
}
frm.total.value = total;
}
For individual radio values use the name - however getting the value directly it will fail if the radio is not checked
var building = frm.querySelector("input[name=building]:checked");
if (building) total += Number(building.value);
To validate, hook up the form's onsubmit
function validate(frm) {
var rads = frm.querySelectorAll('input:checked'); // get all checked radios
if (rads.length<4) {
alert("Please select one of each");
return false; // cancel form
}
return true;
}
window.onload=function() {
document.forms[0].onsubmit=function() {
return validate(this);
}
}
If none of the values are "checked" off then the values are undefined try adding this...
function getRadioValue( radioElement ){
for (var i=0; i < radioElement.length; i++){
if ( radioElement[i].checked ){
return radioElement[i].value;
}
}
}
Replace previous code with this...
var building = getRadioValue( frm.building ) || 0;
var distance = getRadioValue( frm.distance ) || 0;
var age = getRadioValue( frm.age ) || 0;
var sqft = getRadioValue( frm.sqft ) || 0;
var total = 0
Try this:
var building = frm.querySelector("[name=building]:checked");
var distance = frm.querySelector("[name=distance]:checked");
var age = frm.querySelector("[name=age]:checked");
var sqft = frm.querySelector("[name=sqft]:checked");
building = (building && building.value) || 0;
distance = (distance && distance.value) || 0;
age = (age && age.value) || 0;
sqft = (sqft && sqft.value) || 0;

spit items into different arrays and retrieving it back

this related to my previous question asked and thanks to every one here who is helping me to learn coding :D
i was previously working on an undo button which kind of works but not there yet :(
here is what i have done click here. But the problem is since it goes step by step backwards it has to wait till the item where the previous color was applied in the same part. Is there a way i can split something like this click here will this idea work out?
here is the test html code:
<div id="colour">
<input type="submit" name="r1" id="r1" value="1" />
<input type="submit" name="r2" id="r2" value="2" />
<input type="submit" name="r3" id="r3" value="3" />
<input type="submit" name="r4" id="r4" value="4" />
<input type="submit" name="r5" id="r5" value="5" />
<input type="submit" name="r6" id="r6" value="6" />
</div>
<div id="map">
<input type="radio" name="radio" id="layer_a" value="a" />
<label for="layer">layer_a</label>
<input type="radio" name="radio" id="layer_b" value="b" />
<label for="layer">layer_b</label>
<input type="radio" name="radio" id="layer_c" value="c" />
<label for="layer">layer_c</label>
<input type="radio" name="radio" id="layer_d" value="d" />
<label for="layer">layer_d</label>
</div>
<input name="selected" id="selected" type="hidden" value="" />
<input type="submit" name="undo" id="undo" value="undo" />
<div id="result"></div>
here is the test jQuery code:
$("#colour input").click(function() {
$("input[name='selected']").val(this.id);
});
var arraymap = [];
var array_a = [];
var array_b = [];
var array_c = [];
var array_d = [];
$("#map input").click(function() {
var mape = $(this).attr('id');
var ccurrent = $("input[name='selected']").val();
arraymap.push(mape);
// trying to split it into diffrent arrays //
if (mape == "layer_a") {
array_a.push(ccurrent);
var araycurrent = array_a;
} else if (mape == "layer_b") {
array_b.push(ccurrent);
var araycurrent = array_b;
} else if (mape == "layer_c") {
array_c.push(ccurrent);
var araycurrent = array_c;
} else if (mape == "layer_d") {
array_d.push(ccurrent);
var araycurrent = array_d;
};
var mapid = arraymap[arraymap.length - 1];
var colid = arraycurrent[arraycurrent.length - 1];
var loca = mapid + colid;
$("#result").append(mapid);
});
$("#undo").click(function() {
arraymap.pop();
var remover_map = arraymap[arraymap.length - 1];
// trying get it back from split arrays //
if (remover_map == "layer_a") {
array_a.pop();
var remover_col = array_a[array_a.length - 1];
} else if (remover_map == "layer_b") {
array_b.pop();
var remover_col = array_b[array_b.length - 1];
} else if (remover_map == "layer_c") {
array_c.pop();
var remover_col = array_b[array_c.length - 1];
} else if (remover_map == "layer_d") {
array_d.pop();
var remover_col = array_a[array_d.length - 1];
};
var remove = remover_map + remover_col;
$("#result").append(remove);
});
You can store you layer arrays in an object to use it as an associative array. That way you can easily reference them by the layer name.
Here's my version of your example: (Working demo: http://jsfiddle.net/qbdyp/)
var step_layer = []; // layers affected by each step
var step_colour = { // selected colours by layer
"a": [],
"b": [],
"c": [],
"d": []
};
var $map = $("#map"), $result = $("#result"); // cache
$("#colour > input").click(function() {
var layer = $map.find("input[name='radio']:checked").val(); // current layer
var colour = this.value; // selected colour
step_layer.push(layer);
step_colour[layer].push(colour);
$result.append("Added " + colour + " to layer " + layer + "<br/>");
});
$("#undo").click(function() {
var layer = step_layer.pop(); // get most recently changed layer
if (typeof layer === "undefined") {
$result.append("(Nothing to undo)<br />");
return;
}
var colour = step_colour[layer].pop(); // get latest change in that layer
$result.append("Removed " + colour + " from layer " + layer + "<br/>");
});
And here's a more elaborate example, one that's hopefully closer to what you're trying to achieve: http://jsfiddle.net/uWUve/

How can I shift-select multiple checkboxes like GMail?

In GMail, the user can click on one checkbox in the email list, hold down the Shift key, and select a second checkbox. The JavaScript will then select/unselect the checkboxes that are between the two checboxes.
I am curious as to how this is done? Is this JQuery or some basic (or complex) JavaScript?
I wrote a self-contained demo that uses jquery:
$(document).ready(function() {
var $chkboxes = $('.chkbox');
var lastChecked = null;
$chkboxes.click(function(e) {
if (!lastChecked) {
lastChecked = this;
return;
}
if (e.shiftKey) {
var start = $chkboxes.index(this);
var end = $chkboxes.index(lastChecked);
$chkboxes.slice(Math.min(start,end), Math.max(start,end)+ 1).prop('checked', lastChecked.checked);
}
lastChecked = this;
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<head>
</head>
<body>
<input type="checkbox" id="id_chk1" class="chkbox" value="1" />Check 1<br/>
<input type="checkbox" id="id_chk2" class="chkbox" value="2" />Check 2<br/>
<input type="checkbox" id="id_chk3" class="chkbox" value="3" />Check 3<br/>
<input type="checkbox" id="id_chk4" class="chkbox" value="4" />Check 4<br/>
<input type="checkbox" id="id_chk5" class="chkbox" value="5" />Check 5<br/>
<input type="checkbox" id="id_chk6" class="chkbox" value="6" />Check 6<br/>
<input type="checkbox" id="id_chk7" class="chkbox" value="7" />Check 7<br/>
</body>
</html>
This is done through fairly simple javascript.
They keep track of the id of the last checked box and when when another checkbox is checked they use the shiftKey event attribute to see if shift was held while clicking the checkbox. If so they set the checked property of each checkbox in between the two to true.
To determine when a box is checked they probably use an onclick event on the checkboxes
It seems like every answer I can find online is completely dependent on jQuery for this. JQuery adds very little functionality. Here's a quick version that doesn't require any frameworks:
function allow_group_select_checkboxes(checkbox_wrapper_id){
var lastChecked = null;
var checkboxes = document.querySelectorAll('#'+checkbox_wrapper_id+' input[type="checkbox"]');
//I'm attaching an index attribute because it's easy, but you could do this other ways...
for (var i=0;i<checkboxes.length;i++){
checkboxes[i].setAttribute('data-index',i);
}
for (var i=0;i<checkboxes.length;i++){
checkboxes[i].addEventListener("click",function(e){
if(lastChecked && e.shiftKey) {
var i = parseInt(lastChecked.getAttribute('data-index'));
var j = parseInt(this.getAttribute('data-index'));
var check_or_uncheck = this.checked;
var low = i; var high=j;
if (i>j){
var low = j; var high=i;
}
for(var c=0;c<checkboxes.length;c++){
if (low <= c && c <=high){
checkboxes[c].checked = check_or_uncheck;
}
}
}
lastChecked = this;
});
}
}
And then initialize it whenever you need it:
allow_group_select_checkboxes('[id of a wrapper that contains the checkboxes]')
Recently, I wrote a jQuery plugin that provide that feature and more.
After including the plugin you just need to initialize the context of checkboxes with the following code snippet:
$('#table4').checkboxes({ range: true });
Here is the link to the documentation, demo & download: http://rmariuzzo.github.io/checkboxes.js/
Well, the post is quite old but here is a solution I've just come across:
jQuery Field Plug-In
I took the jQuery version from #BC. and transformed it into an ES6 version, since the code is actually pretty elegantly solving the problem, in case anyone still stumbles across this...
function enableGroupSelection( selector ) {
let lastChecked = null;
const checkboxes = Array.from( document.querySelectorAll( selector ) );
checkboxes.forEach( checkbox => checkbox.addEventListener( 'click', event => {
if ( !lastChecked ) {
lastChecked = checkbox;
return;
}
if ( event.shiftKey ) {
const start = checkboxes.indexOf( checkbox );
const end = checkboxes.indexOf( lastChecked );
checkboxes
.slice( Math.min( start, end ), Math.max( start, end ) + 1 )
.forEach( checkbox => checkbox.checked = lastChecked.checked );
}
lastChecked = checkbox;
} ) );
}
Got this solution from http://abcoder.com/javascript/jquery/simple-check-uncheck-all-jquery-function/ (now dead):
JavaScript and HTML code
var NUM_BOXES = 10;
// last checkbox the user clicked
var last = -1;
function check(event) {
// in IE, the event object is a property of the window object
// in Mozilla, event object is passed to event handlers as a parameter
if (!event) { event = window.event }
var num = parseInt(/box\[(\d+)\]/.exec(this.name)[1]);
if (event.shiftKey && last != -1) {
var di = num > last ? 1 : -1;
for (var i = last; i != num; i += di) {
document.forms.boxes['box[' + i + ']'].checked = true;
}
}
last = num;
}
function init() {
for (var i = 0; i < NUM_BOXES; i++) {
document.forms.boxes['box[' + i + ']'].onclick = check;
}
}
<body onload="init()">
<form name="boxes">
<input name="box[0]" type="checkbox">
<input name="box[1]" type="checkbox">
<input name="box[2]" type="checkbox">
<input name="box[3]" type="checkbox">
<input name="box[4]" type="checkbox">
<input name="box[5]" type="checkbox">
<input name="box[6]" type="checkbox">
<input name="box[7]" type="checkbox">
<input name="box[8]" type="checkbox">
<input name="box[9]" type="checkbox">
</form>
</body>
Inspired by the fine answers provided, here's a plain JavaScript version using Array.prototype to coerce nodelists to use array functions, rather than for loops.
(function () { // encapsulating variables with IIFE
var lastcheck = null // no checkboxes clicked yet
// get desired checkboxes
var checkboxes = document.querySelectorAll('div.itemslist input[type=checkbox]')
// loop over checkboxes to add event listener
Array.prototype.forEach.call(checkboxes, function (cbx, idx) {
cbx.addEventListener('click', function (evt) {
// test for shift key, not first checkbox, and not same checkbox
if ( evt.shiftKey && null !== lastcheck && idx !== lastcheck ) {
// get range of checks between last-checkbox and shift-checkbox
// Math.min/max does our sorting for us
Array.prototype.slice.call(checkboxes, Math.min(lastcheck, idx), Math.max(lastcheck, idx))
// and loop over each
.forEach(function (ccbx) {
ccbx.checked = true
})
}
lastcheck = idx // set this checkbox as last-checked for later
})
})
}())
<div class="itemslist">
<input type="checkbox" name="one" value="1">
<input type="checkbox" name="two" value="2">
<input type="checkbox" name="three" value="3">
<input type="checkbox" name="four" value="4">
<input type="checkbox" name="five" value="5">
</div>
I realy liked gyo's example and added some code so it works on all checkboxes with the same name.
I also added a MutationObserver so events are also handled on newly added checkboxes.
$(document).ready(function() {
var previouslyClicked = {};
var rangeEventHandler = function(event) {
if (event.shiftKey && previouslyClicked[this.name] && this != previouslyClicked[this.name]) {
var $checkboxes = $('input[type=checkbox][name='+this.name+']').filter(':visible');
var start = $checkboxes.index( this );
var end = $checkboxes.index( previouslyClicked[this.name] );
// console.log('range', start, end, this, previouslyClicked[this.name]);
$checkboxes.slice(Math.min(start,end), Math.max(start,end)+ 1).prop('checked', previouslyClicked[this.name].checked);
} else {
previouslyClicked[this.name] = this;
}
};
if ("MutationObserver" in window) { // https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver/MutationObserver to refresh on new checkboxes
var mutationCallback = function(mutationList, observer) {
mutationList.forEach((mutation) => {
mutation.addedNodes.forEach((node) => {
if (node.nodeName == 'INPUT' && node.type == 'checkbox') {
$(node).on('click.selectRange', rangeEventHandler);
}
});
});
};
var observer = new MutationObserver(mutationCallback);
observer.observe(document, {
childList: true,
attributes: false, // since name is dynamically read
subtree: true
});
}
$('input[type=checkbox][name]').on('click.selectRange', rangeEventHandler);
});
<html>
<head>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
First:
<input type="checkbox" name="first">
<input type="checkbox" name="first">
<input type="checkbox" name="first">
<input type="checkbox" name="first">
<input type="checkbox" name="first">
</div>
<div>
Second:
<input type="checkbox" name="second">
<input type="checkbox" name="second">
<input type="checkbox" name="second">
<input type="checkbox" name="second">
<input type="checkbox" name="second">
</div>
</body>
</html>
Found the better solution it works for both select and deselects checkboxes.
Uses a core javascript & Jquery.
$(document).ready(function() {
var $chkboxes = $('.chkbox');
var lastChecked = null;
$chkboxes.click(function(e) {
if(!lastChecked) {
lastChecked = this;
return;
}
if(e.shiftKey) {
var start = $chkboxes.index(this);
var end = $chkboxes.index(lastChecked);
$chkboxes.slice(Math.min(start,end), Math.max(start,end)+ 1).prop('checked', e.target.checked);
}
lastChecked = this;
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<head>
</head>
<body>
<input type="checkbox" id="id_chk1" class="chkbox" value="1" />Check 1<br/>
<input type="checkbox" id="id_chk2" class="chkbox" value="2" />Check 2<br/>
<input type="checkbox" id="id_chk3" class="chkbox" value="3" />Check 3<br/>
<input type="checkbox" id="id_chk4" class="chkbox" value="4" />Check 4<br/>
<input type="checkbox" id="id_chk5" class="chkbox" value="5" />Check 5<br/>
<input type="checkbox" id="id_chk6" class="chkbox" value="6" />Check 6<br/>
<input type="checkbox" id="id_chk7" class="chkbox" value="7" />Check 7<br/>
</body>
</html>
Here is also another implementation similar to Outlooks multiple selection..
<script type="text/javascript">
function inRange(x, range)
{
return (x >= range[0] && x <= range[1]);
}
$(document).ready(function() {
var $chkboxes = $('.chkbox');
var firstClick = 1;
var lastClick = null;
var range = [];
$chkboxes.click(function(e) {
if(!e.shiftKey && !e.ctrlKey) {
$('#index-' + firstClick).prop('checked', false);
firstClick = $chkboxes.index(this) + 1;
if (firstClick !== null && firstClick !== ($chkboxes.index(this)+1)) {
$('#index-' + firstClick).prop('checked', true);
}
} else if (e.shiftKey) {
lastClick = $chkboxes.index(this) + 1;
if ((firstClick < lastClick) && !inRange(lastClick, range)) {
for (i = firstClick; i < lastClick; i++) {
$('#index-' + i).prop('checked', true);
}
range = [firstClick, lastClick];
} else if ((firstClick > lastClick) && !inRange(lastClick, range)) {
for (i = lastClick; i < firstClick; i++) {
$('#index-' + i).prop('checked', true);
}
range = [lastClick, firstClick];
} else if ((firstClick < lastClick) && inRange(lastClick, range)) {
for (i = 1; i < 100; i++) {
$('#index-' + i).prop('checked', false);
}
for (i = firstClick; i < lastClick; i++) {
$('#index-' + i).prop('checked', true);
}
range = [firstClick, lastClick];
}else if ((firstClick > lastClick) && inRange(lastClick, range)) {
for (i = 1; i < 100; i++) {
$('#index-' + i).prop('checked', false);
}
for (i = lastClick; i < firstClick; i++) {
$('#index-' + i).prop('checked', true);
}
range = [lastClick, firstClick];
}
}
});
});
This is jquery solution that I wrote and use:
All checkboxes have same class named chksel
For faster individual selection a class will carry the order
named chksel_index
Also each checkbox has an attribute named rg that contain same
index
var chksel_last=-1;
$('.chksel').click(function(ev){
if(ev.shiftKey){var i=0;
if(chksel_last >=0){
if($(this).attr('rg') >= chksel_last){
for(i=chksel_last;i<=$(this).attr('rg');i++){$('.chksel_'+i).attr('checked','true')}}
if($(this).attr('rg') <= chksel_last){for(i=$(this).attr('rg');i<=chksel_last;i++){$('.chksel_'+i).attr('checked','true')}}
}
chksel_last=$(this).attr('rg');
}else{chksel_last=$(this).attr('rg');}
})
this solution works for me, also ajax based for DataTables
https://jsfiddle.net/6ouhv7bw/4/
<table id="dataTable">
<tbody>
<tr>
<td><input type="checkbox"></td>
</tr>
<tr>
<td><input type="checkbox"></td>
</tr>
<tr>
<td><input type="checkbox"></td>
</tr>
<tr>
<td><input type="checkbox"></td>
</tr>
</tbody>
</table>
<script>
$(document).ready(function() {
var $chkboxes = $('#dataTable');
var $range = '#dataTable tbody';
var $first = false;
var $indexWrapp = 'tr';
var lastChecked = null;
var $checkboxes = 'input[type="checkbox"]';
$chkboxes.on('click',$checkboxes,function(e) {
if ($first===false) {
lastChecked = $(this).closest($indexWrapp).index();
lastCheckedInput = $(this).prop('checked');
$first=true;
return;
}
if (e.shiftKey) {
var start = lastChecked;
var end = $(this).closest($indexWrapp).index();
$( $range+' '+$indexWrapp).each(function() {
$currIndex=$(this).index();
if( $currIndex>=start && $currIndex<=end ){
$(this).find($checkboxes).prop('checked', lastCheckedInput);
}
})
}
lastCheckedInput = $(this).prop('checked');
lastChecked = $(this).closest($indexWrapp).index();
});
</script>
Here is the Elegant implementation. The idea is to store the first selected input to the lastChecked variable and when the user selects the input field with shiftKey we will run a loop and toggle the inBetween(boolean) and mark all the checkboxes with true value.
Inspired by Wesbos.
let checkboxes = document.querySelectorAll('.wrapper input[type="checkbox"]');
let lastChecked;
function logic(e) {
let inBetween = false;
if (e.shiftKey) {
checkboxes.forEach(checkbox => {
if (checkbox === this || checkbox === lastChecked) {
inBetween = !inBetween;
}
if (inBetween) checkbox.checked = true;
})
}
lastChecked = this;
}
checkboxes.forEach((checkbox, i) => checkbox.addEventListener('click', logic));
.wrapper {
display: flex;
flex-direction: column;
}
<div class="wrapper">
<input type="checkbox" name="one">
<input type="checkbox" name="two">
<input type="checkbox" name="three">
<input type="checkbox" name="four">
<input type="checkbox" name="five">
</div>

Categories