How to grab values of checkboxes in an array - javascript

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>

Related

I want to catch all labels of checked checkbox in javascript

Is there a way to catch all the label texts of a checked checkbox in Javascript (not JQuery).
My HTML is:
<div class="wpgu-onboarding-answer-container">
<div class="wpgu-onboarding-answer" data-bc-answer-post="Firstitem">
<input id="post-3-0" class="wpgu-onboarding-answer-checkbox" type="checkbox" name="posts_stijlen[]" value="670" checked="checked">
<label for="post-3-0" class="wpgu-onboarding-answer-label">
<span class="wpgu-onboarding-answer-title">Firstitem</span>
</label>
</div>
<div class="wpgu-onboarding-answer" data-bc-answer-post="SecondItem">
<input id="post-3-8" class="wpgu-onboarding-answer-checkbox" type="checkbox" name="posts_stijlen[]" value="681">
<label for="post-3-8" class="wpgu-onboarding-answer-label">
<span class="wpgu-onboarding-answer-title">SecondItem</span>
</label>
</div>
</div>
I want to catch the label of the checked checkbox in Javascript in order to use it as Javascript Variable in Google Tagmanager.
Currently I've got this code (from www.simoahava.com) to catch the values of the checked checkboxes.
function () {
var inputs = document.querySelectorAll('.wpgu-onboarding-answer-containter input'),
selectedCheckboxes = [];
for (var i = 0; i < inputs.length; i++) {
if (inputs[i].type === "checkbox" && inputs[i].checked) {
selectedCheckboxes.push(inputs[i].value);
}
}
return selectedCheckboxes;
}
This script gives me all the values, but these are none-descriptive values. But I want the descriptive labels.
Is there a way to catch the text within the span with class .wpgu-onboarding-answer-title of all checked checkboxes ?
Thanks in Advance
Erik.
Apart from the previous solution, would like to share one more simple solution based on the code mentioned in the question. The solution can be as simple as fetching all the labels with class as wpgu-onboarding-answer-title and based on which input element is selected, fetch the respective label index and use it.
Please note that I have added an extra button for testing the function easily.
function abc() {
var labels = document.querySelectorAll('.wpgu-onboarding-answer-title');
var inputs = document.querySelectorAll('.wpgu-onboarding-answer-container input'),
selectedCheckboxes = [];
for (var i = 0; i < inputs.length; i++) {
if (inputs[i].type === "checkbox" && inputs[i].checked) {
selectedCheckboxes.push(labels[i].textContent);
//selectedCheckboxes.push(inputs[i].value);
}
}
console.log(selectedCheckboxes);
return selectedCheckboxes;
}
<div class="wpgu-onboarding-answer-container">
<div class="wpgu-onboarding-answer" data-bc-answer-post="Firstitem">
<input id="post-3-0" class="wpgu-onboarding-answer-checkbox" type="checkbox" name="posts_stijlen[]" value="670" checked="checked">
<label for="post-3-0" class="wpgu-onboarding-answer-label">
<span class="wpgu-onboarding-answer-title">Firstitem</span>
</label>
</div>
<div class="wpgu-onboarding-answer" data-bc-answer-post="SecondItem">
<input id="post-3-8" class="wpgu-onboarding-answer-checkbox" type="checkbox" name="posts_stijlen[]" value="681">
<label for="post-3-8" class="wpgu-onboarding-answer-label">
<span class="wpgu-onboarding-answer-title">SecondItem</span>
</label>
</div>
</div>
<button onclick="abc()">
Fetch All Chkbox Values
</button>
Please note that this solution would only work if you have wpgu-onboarding-answer-title class being used for only this purpose and not anywhere else in the page before.
Based on this answer using jQuery, you can use an attribute selector and the ID of the element you want to get the label for, e.g. document.querySelector('label[for=' + button.id + ']'), then get its textContent to get the actual label:
document.querySelectorAll('input.wpgu-onboarding-answer-checkbox').forEach(input => {
console.log(input.id + ' ' +
document.querySelector('label[for=' + input.id + ']').textContent.trim() + ' ' +
(input.checked? '' : 'not ') + 'checked'
)
});
<div class="wpgu-onboarding-answer-container">
<div class="wpgu-onboarding-answer" data-bc-answer-post="Firstitem">
<input id="post-3-0" class="wpgu-onboarding-answer-checkbox" type="checkbox" name="posts_stijlen[]" value="670" checked="checked">
<label for="post-3-0" class="wpgu-onboarding-answer-label">
<span class="wpgu-onboarding-answer-title">Firstitem</span>
</label>
</div>
<div class="wpgu-onboarding-answer" data-bc-answer-post="SecondItem">
<input id="post-3-8" class="wpgu-onboarding-answer-checkbox" type="checkbox" name="posts_stijlen[]" value="681">
<label for="post-3-8" class="wpgu-onboarding-answer-label">
<span class="wpgu-onboarding-answer-title">SecondItem</span>
</label>
</div>
</div>
This could help you.
var inputs = document.querySelectorAll(".wpgu-onboarding-answer-container input:checked+label>span");
var checkbox = [];
inputs.forEach(input=>{
checkbox.push(input.textContent);
console.log(input.textContent)
});
Good lucky!

merging checkbox selection into appendChild

I'm currently creating a Checkbox and trying to append the selections to a function.
This is what I currently have :
<input type="checkbox" id="Animal" value="Animal" name="langs" checked><label for="UW">UW</label><br>
<input type="checkbox" id="Vegatable" value="Vegetable" name="langs"><label for="OIB">OIB</label><br>
<input type="text" id="Other" value="N/A" name="langs" style="font-size:10px;" style="width: 125px;" /><label for="Other">Other</label><br>
This is what I currently have for the Appendchild Result:
<tr name="checkbox_value"><th>Systems Used: </th>
</tr>
I'm using the option Document.getElementId but I can't get multiple result or a single result
var SysRow = document.getElementById("checkbox_value");
var td4 = document.createElement("td");
td4.innerHTML = document.getElementById("langs").value;
SysRow.appendChild(td4);
from my understanding i can use document.getElementsByClassName() or document.querySelectorAll() but I'm not sure how to implement it .
What if the person selects multiple results like "Animal" and "Vegetable".
Use this code:
var items=document.getElementsByClassName('appendInput');
var checkedItems ="";
for(var i=0; i<items.length; i++){
if(items[i].type=='checkbox' && items[i].checked)
checkedItems+=items[i].value+" ";
}
document.getElementById('result').innerHTML = checkedItems;
<input class="appendInput" type="checkbox" name="langs" value="Animal" checked>
<input class="appendInput" type="checkbox" name="langs" value="Vegetable" checked>
<input class="appendInput" type="checkbox" name="langs" value="N/A">
<div id="result"></div>
Add a class on the elements that you want to append
<input class="toappend" type="text" name="element_1">
<input class="toappend" type="text" name="element_2">
<input class="toappend" type="text" name="element_3">
Then in JS
var allElements = document.querySelectorAll('.toappend');
allElements will become nodeList then you can pass it in the function
function yourFunction(elements) {
// If you want to use forEach method, you have to convert the nodeList to an Array
//ES5
var arrElements = Array.prototype.slice.call(elements);
//ES6
let arrElements = Array.from(elements);
arrElements.forEach(function(currentEl, index, array) {
var appendTo = document.querySelector('#checkbox_value');
appendTo.insertAdjacentHTML('beforeend', currentEl.outerHTML);
});
}
Check this pen

Trying to validate values inside a loop

Trying to validate a multi-form data. If class "a" is checked it has to check whether class "b" is empty or not.
c = 1;
d = 1;
$('.a').each(function() {
if ($(this).is(':checked')) {
$('.b').each(function() {
if ($(this).val() == '') {
err += "<p>Value Empty at row +c+</p>";
return false;
}
d = d + 1;
});
}
c = c + 1;
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label><input type="checkbox" class="a" name="a[]" value="Value" /> Value</label><br> <input type="text" class="b" name="b[]" />
The Issue is, it validates perfectly for the first form. when it comes to second form, it checks the first value of class 'b' instead of checking second value of class 'b'
You don't want the .b loop inside the .a loop. You want a single loop handling both:
var checkboxes = $(".a");
var textboxes = $(".b");
for (var n = 0; n < checkboxes.length; ++n) {
if (checkboxes[n].checked && !textboxes[n].value.trim()) {
err += "<p>Value Empty at row " + n + "</p>";
}
}
Live Example:
$("#btn").on("click", function() {
var err = "";
var checkboxes = $(".a");
var textboxes = $(".b");
for (var n = 0; n < checkboxes.length; ++n) {
if (checkboxes[n].checked && !textboxes[n].value.trim()) {
err += "<p>Value Empty at row " + n + "</p>";
}
}
$("#err").html(err);
});
<label><input type="checkbox" class="a" name="a[]" value="Value" /> Value</label><br> <input type="text" class="b" name="b[]" />
<br>
<label><input type="checkbox" class="a" name="a[]" value="Value" /> Value</label><br> <input type="text" class="b" name="b[]" />
<br>
<label><input type="checkbox" class="a" name="a[]" value="Value" /> Value</label><br> <input type="text" class="b" name="b[]" />
<br>
<input type="button" id="btn" value="Check">
<div id="err"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
A couple of notes:
When you use [n] to index into a jQuery object, you get the raw DOM element at that position. When you have the raw element, there's no need for .is(":checked"), just use the checked property on the element itself. (So: checkboxes[n].checked instead of $(checkboxes[n]).is(":checked") or checkboxes.eq(n).is(":checked").)
Similarly, input elements have their own value property, no need to wrap them in an jQuery object just to call val().
My code above assumes that an input containing only whitespace should be considered empty. It does that with String#trim, which was introduced in ES5 (2009). If you need to support seriously obsolete browsers like IE8, you may need a polyfill for it.
When you use the code
$(".b")...
it checks all inputs with class b, but you only want the related one. The key is determining how they are related. It could be they are in a parent div or they could be matched using data- attributes, or could simply be the "next" input.
Your example HTML only shows one 'pair' of .a and .b, so if we expand that pair to multiple pairs, eg grouped in a 'group' div, you can then use .closest(".group") to find the containing div and then the related .b within that div:
$("#validate").click(function() {
var c = 1;
var d = 1;
var err = "";
$('.a').each(function() {
if ($(this).is(':checked')) {
// only find the related `.b`
//$('.b').each(function() {
$(this).closest(".group").find(".b").each(function() {
if ($(this).val() == '') {
err += "<p>Value Empty at row " + c + "</p>";
return false;
}
d = d + 1;
});
}
c = c + 1;
});
console.log("c:", c, "d:", d, err);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='group'>
<label>
<input type="checkbox" class="a" name="a[]" value="Value" />
Value
</label>
<br>
<input type="text" class="b" name="b[]" />
</div>
<div class='group'>
<label>
<input type="checkbox" class="a" name="a[]" value="Value" />
Value
</label>
<br>
<input type="text" class="b" name="b[]" />
</div>
<button id='validate' type='button'>validate</button>
When you're doing $('.b').each(function(){}) it's finding all the elements with class .b again/each time. Hence checking for first element again.
One solution would be to first find all the elements and then run the loop and use index to find the elements
as = $(".a");
bs = $(".b");
for(var i = 0; i < as.length; i++){
a = as[i];
b = bs[i];
if($(a).is(':checked')){
if($(b).val() === ''){
err += "<p>Value Empty at row +c+</p>";
return false;
}
}
}
Or structure your markup a in such a way where all the related elements with class a & b are put inside a div.
You can find all the .a and while looping you'll find all the .b inside the parent div
<div class='wrapper-related-fields'>
<label><input type="checkbox" class="a" name="a[]" value="Value" /> Value</label>
<br>
<input type="text" class="b" name="b[]" />
</div>
$('.a').each(function(){
if($(this).is(':checked')){
// Find the parent wrapper
wrapper = $(this).closest(".wrapper-related-fields");
// find all the .b elements inside wrapper
$(warpper).find('.b').each(function(){
if($(this).val() == '')
{
err += "<p>Value Empty at row +c+</p>";
return false;
}
d = d + 1;
});
}
c = c + 1;
});

querySelectorAll loop "undefined"

I try to loop over few input elements in order to get each value, but for some reason I only get the last one:
<input type="text" name="input-loop" data-loop="true" />
<input type="text" name="input-loop" data-loop="true" />
<input type="text" name="input-loop" data-loop="true" />
<button type="button" onclick="loop()">loop</button>
<div id="output"></div>
<script>
function loop() {
var element = document.querySelectorAll('[data-loop="true"]');
for(var i = 0; i < element.length; i++) {
console.log(element[i].length);
// or:
// document.getElementById('output').innerHTML = element[i].value + '<br>';
}
}
</script>
The console shows undefined and when I try to output the values, I only get it from the last element and not from all of them. What am I doing wrong?
Thank you very much (and please excuse my english)
You are trying to get the length of the element itself:
console.log(element[i].length);
Elements don't have a length.
I suspect you are trying to get the length of the value of the elements:
console.log(element[i].value.length);
function loop() {
// elements will be a "node list" containing any/all elements
// that match the query.
var elements = document.querySelectorAll('[data-loop="true"]');
// Because it is a node list, which is an array-like object,
// it has a "length" property:
console.log("There were " + elements.length + " elements found.");
// ...And, it can be looped through
for(var i = 0; i < elements.length; i++) {
// It's contained elements are indexed and when you do that,
// you may access properties of the elements themselves
console.log(elements[i].value);
// or:
document.getElementById('output').innerHTML += elements[i].value + '<br>';
}
}
<p>Type some text in the textboxes and then click the button:</p>
<input type="text" name="input-loop" data-loop="true" />
<input type="text" name="input-loop" data-loop="true" />
<input type="text" name="input-loop" data-loop="true" />
<button type="button" onclick="loop()">loop</button>
<div id="output"></div>
try to console.log(element[i]); This is because here element will be a collection of DOM elements.
There is no length property for these elements.
Since they are input and if you want to get their value you need to log
element[i].value
What am I doing wrong?
console.log(element[i].length);
element[i] refers to an HTMLInputElement. It and non of its parent classes have a length property. Assuming you want to display the length of the value of the input element, the following would work.
var output = document.getElementById('output');
function loop() {
var element = document.querySelectorAll('[data-loop="true"]');
element.forEach( (e) => {
output.innerHTML += `${e.value}: ${e.value.length}<br>`;
});
}
function clearOutput(){
output.innerHTML = '';
}
<input type="text" name="input-loop" data-loop="true" value="one" />
<input type="text" name="input-loop" data-loop="true" value="two" />
<input type="text" name="input-loop" data-loop="true" value="three" />
<button type="button" onclick="loop()">loop</button>
<button type="button" onclick="clearOutput()">clear</button>
<div id="output"></div>

How to detect which element contains all other X elements

(Hope this question hasn't been asked yet : I didn't find it via a keyword search)
I'd like to detect, using jQuery, which element (div, span, anything) contains all the other XKindOfElement.
Meaning, for example, if I have multiple checkboxes in my screen, I want to know which div contains all those checkboxes.
<div id="block1">
<div id="underblock1">
<input type="checkbox" name="thing[]" value="1" />
<div id="underunderblock1">
<input type="checkbox" name="thing[]" value="2" />
</div>
</div>
<div id="underblock2">
<input type="checkbox" name="thing[]" value="3" />
</div>
</div>
In this example, it will return the div#block1 because only it contains all the input[type="checkbox"] of the page.
Hope you'll understand and could help me !
UPDATE
Thinking of something... What do you think about this process :
Check if our element exists in the page
If so, count how many of this element exists and save it (let's say count)
Check if the parent of the first element find contains all the count elements
If not, check if the parent of the parent contains all the count elements,
etc
When the checked parent does contain all the count elements: it is our "smallest global parent" !
Would it be ok or too slow, too "expansive"... ?
I'm not very familiar with all the jQuery helper methods, but this approach might work for you:
Collect all the elements you want to be included
Collect their parents arrays and reverse them: all these arrays now start with: html > body and continue all the way to the actual element
loop through a parent array and check if the other parent arrays have the same element at the current index
the first element that doesn't match marks the index of the last shared parent
Note: you might want to refactor the code a bit to make sure you don't run into any errors for edge cases.
var required = $("input[type=checkbox]");
var getClosestParent = function(elements) {
var maxLength = 0;
var allParents = [];
elements.each(function(i, el) {
var parents = $(el).parents().toArray().reverse();
maxLength = Math.max(maxLength, parents.length);
allParents.push(parents);
});
var ref = allParents[0];
var others = allParents.slice(1);
for (var i = 0; i < maxLength; i += 1) {
for (var j = 0; j < others.length; j += 1) {
if (ref[i] !== others[j][i]) {
return ref[i - 1];
}
}
}
return null;
}
console.log(getClosestParent(required).id);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="block1">
<div id="underblock1">
<input type="checkbox" name="thing[]" value="1" />
<div id="underunderblock1">
<input type="checkbox" name="thing[]" value="2" />
</div>
</div>
<div id="underblock2">
<input type="checkbox" name="thing[]" value="3" />
</div>
</div>
Get an array of arrays for each of the parents, then loop over them until you find a miss-match:-
var parents = new Array();
var minDepth = (Math.pow(2, 53) - 1);
$('[type=checkbox]').each(function(i, e) {
parents.push($(e).parents().get().reverse());
if (minDepth > parents[i].length)
minDepth = parents[i].length;
});
var topParent, testParent;
finished:
for (var i = 0; i < minDepth; i++) {
testParent = parents[0][i];
for (var j = 0; j < parents.length; j++) {
if (parents[j][i] != testParent)
break finished;
}
topParent = parents[0][i];
}
console.log(topParent);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="block1">
<div id="underblock1">
<input type="checkbox" name="thing[]" value="1" />
<div id="underunderblock1">
<input type="checkbox" name="thing[]" value="2" />
</div>
</div>
<div id="underblock2">
<input type="checkbox" name="thing[]" value="3" />
</div>
</div>
Ok so, I'm answering to myself thx to you guys. I thought about #user3297291 said, however I still think starting from the element itself is faster than starting from html > body > etc.
So I make this, what do you think ?
var required = jQuery("input[type=checkbox]");
var getClosestGlobalParent = function(elements) {
var count = elements.length,
result = null;
if(count) {
if(count > 1) {
jQuery(elements[0]).parents().each(function(i, el) {
if(jQuery(this).find(elements).length == count) {
result = jQuery(this); // We also can return "this"
return false; // If the parent is found, we stop the .each loop
}
});
} else {
result = jQuery(elements[0]).parent(); // If there's only one element, his closest parent IS his .parent()
}
}
return result;
}
console.log(getClosestGlobalParent(required).attr('id'));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<div id="under_container">
<div id="block1">
<div id="underblock1">
<input type="checkbox" name="thing[]" value="1" /> Val1
<div id="underunderblock1">
<input type="checkbox" name="thing[]" value="2" /> Val2
</div>
</div>
<div id="underblock2">
<input type="checkbox" name="thing[]" value="3" /> Val3
<br /><input type="checkbox" name="thing[]" value="4" /> Val4
</div>
</div>
</div>
</div>
$.fn.sharedParents = function(){
if (this.length == 0)
return this;
var parents = $(this.get(0)).parents();
for (var i=0; i<parents.length; i++)
for (var j=1; j<this.length; j++)
if (!$.contains(parents[i], this[j]))
{
delete parents[i];
break;
}
return parents;
}
For given set of elements - get all the parents of the first element. Then for all the other elements check if given parents contain those elements. The result is a list of all parents containing all elements, and, as such, the deepest parent will be the first entry of that list.
https://jsfiddle.net/hwte8n3w/

Categories