I have a series of a series of rows and checkboxes to filter them:
<ul>
<li><input id="type-A" type="checkbox" checked="checked"> A</li>
<li><input id="type-B" type="checkbox" checked="checked"> B</li>
<li><input id="type-C" type="checkbox" checked="checked"> C</li>
<li><input id="type-D" type="checkbox" checked="checked"> D</li>
<li><input id="type-E" type="checkbox" checked="checked"> E</li>
<li><input id="type-F" type="checkbox" checked="checked"> F</li>
</ul>
<table>
<tr class="A">filler</tr>
<tr class="B">filler</tr>
<tr class="A B">filler</tr>
<tr class="C D">filler</tr>
<tr class="A F">filler</tr>
<tr class="A E F">filler</tr>
<tr class="F">filler</tr>
<tr class="C D E">filler</tr>
<tr class="A B C D E F">filler</tr>
</table>
I'd like to hide/show rows based on what is checked. Currently I'm using (with the help from this previous question: Use "this" to simplify code (simple jQuery) ):
$(function(){
$("input[id^='type-']").change(function() {
$("."+this.id.replace('type-','')).toggle(this.checked);
}).change();
});
Which toggles what is shown every time a box is clicked and works great if each row only has one class. But they don't. How it's set up now, the order of clicking changes the rows that are shown. So I need to create a function that checks which checkboxes are checked and shows the rows that contain any of them. I'm not opposed to adding a button to make this happen.
I'd appreciate any help (and the direction to resources that could help me learn) you guys could give me!
Modify the function to get a selector for all the checked check boxes.
$(function(){
var $checkboxes = $("input[id^='type-']");
$checkboxes.change(function() {
var selector = '';
$checkboxes.filter(':checked').each(function(){ // checked
selector += '.' + this.id.replace('type-','') + ', ';
// builds a selector like '.A, .B, .C, '
});
selector = selector.substring(0, selector.length - 2); // remove trailing ', '
// tr selector
$('table tr').hide() // hide all rows
.filter(selector).show(); // reduce set to matched and show
}).change();
});
EDIT: see jsfiddle
jQuery has created this function for you! It's called .filter(), and it takes either a selector string, a function, a raw DOM element, or a jQuery object. In your case, I'd pass it a selector string. We can make use of jQuery's :has() selector, which takes a selector and returns the matched elements. So, if you wanted to select all rows (li elements) that contain checked checkboxes, you could do it like this:
$("li").filter(":has(input:checked)");
Or, we could eliminate our call to filter() and simply pass the entire selector to $():
$("li:has(input:checked)");
That will return all li elements that contain any checked checkboxes anywhere among it's descendants, not just it's direct children.
And putting it in the context of your .change() handler:
I'm assuming you want to show tr elements that have the same type as the li elements that contain checked checkboxes, and hide any tr elements that don't. So, we'll make use of the .toggle() function, which toggles the visibility of elements:
$(function(){
$("input[id^='type-']").change(function() {
$("."+this.id.replace('type-','')).toggle(this.checked);
// show any tr elements that have the class relating to the type of the inputs that contain checked checkboxes...
$("li:has(input:checked)").each(function() {
$("tr" + "." + this.id.replace(/type-/, "")).toggle();
});
}).change();
});
$("table tr").hide();
$("input[id^='type-']").each(function() {
element = $(this);
$("table tr").each(function() {
if($(this).hasClass(element.id.replace('type-','')) {
if(element.is(":checked") {
element.show();
}
}
});
}).change();
Related
I have an idea to add a dynamic css style by changing my label and make my input elements show differently when item.areaNo changes. I successfully gave my label element class='1', but css class did not understand my selector.I really need to know how to set the correct one.
<ol class="cabin fuselage">
<li class="row row--1">
<ol class="seats" type="A">
<li class="seat"><input type="checkbox" id="01-01" />
<label for="01-01">01-01</label></li>
<li class="seat"><input type="checkbox" id="02-01" /> <label
for="02-01">02-01</label></li>
this is my jsp,
.seat label.1{background: #50bdc9;}
and my css,
both reference to https://codepen.io/siiron/pen/MYXZWg BY Ronny Siikaluoma
$.getJSON("gametransfer.controller", function(json) {
$.each(Object.values(json), function(i, item) {
console.log(item)
var aa = '#' + item.seatNo;
if ($('.seat>input').is(aa)) {
if (item.attr == true) {
$(aa).prop('disabled', true);
}
$(aa).siblings('label').addClass('1');
}/*end of outer if */
});
});
solved :all of those attempts failed and return with all of the item.areaNo in first label elements.
You need find no. of a child (li.seat) then you can use for loop then find label one by one and put different CSS for each label. I hope it's work.
This question already has answers here:
jquery, find next element by class
(5 answers)
Closed 6 years ago.
When any checkbox with class .child-term is checked, I automatically need to check the preceding checkbox with class .parent-term.
I only want to check the preceding .parent-term class not all the checkboxes that have .parent-class. Same goes for the .child-term class. Any checkbox with .child-term only affects the .parent-term above.
If the .parent-term class was checked from a .sub-term checkbox the .parent-term can remain checked when all the associated .sub-term boxes are unchecked.
I have tried various solutions, but I can't figure it out.
I started a jsfiddle.
<ul class="cpt-terms-checkbox">
<li class="parent-term church" id="category-church"><input id="church"
name="church" type="checkbox" value="church">Church</li>
<li><small>Sub Categories:</small></li>
<li class="child-term elder" id="category-elder"><input id="elder"
name="elder" type="checkbox" value="elder">Elder</li>
<li class="child-term interim-pastor" id="category-interim-pastor">
<input id="interim-pastor" name="interim-pastor" type="checkbox" value=
"interim-pastor">Interim Pastor</li>
<li class="parent-term law-firm" id="category-law-firm"><input id=
"law-firm" name="law-firm" type="checkbox" value="law-firm">Law
Firm</li>
<li><small>Sub Categories:</small></li>
<li class="child-term attorney" id="category-attorney"><input id=
"attorney" name="attorney" type="checkbox" value=
"attorney">Attorney</li>
<li class="child-term attorney" id="category-attorney"><input id=
"attorney" name="attorney" type="checkbox" value=
"attorney">Paralegal</li>
</ul>
Adding to Anoop Joshi's solution . . . I changed .parent() to .parents() so it would move up higher and for those who may run this in Wordpress I wrapped it in an anonymous function.
(function($) {
$(".child-term :input").change(function() {
if (this.checked) {
$(this).parents().prevAll(".parent-term:first").find("input").prop("checked", true);
}
});
})( jQuery );
Use prevAll() to get all the previous nodes with specified selector.
Then you can use the :first selector to get the immediate previous element
$(".child-term :input").change(function() {
if (this.checked) {
$(this).parent().prevAll(".parent-term:first").find("input").prop("checked", true);
}
});
Fiddle
So here's my problem, I'm new to jQuery. What I am trying to do here is check for user to click on a certain table cell/row and it would then display a div named popup of an index the same as the table cell votes. Without having to make separate functions of all the rows in my table.
Using some numerical value will display all the dialogs from a click of the cell of the same value the first time and from the second time only the correct one.
I bet there's some other way to do it and maybe there's just a stupid error.
Using the index value in the click and dialog function won't work.
I am open to suggestions on improvement also.
The scripts:
<script type='text/javascript'>
$(document).ready( function() {
$('.votes').each(function(index) {
$('.votes:eq(index)').click(function() {
$('.popup:eq(index)').dialog();
});
});
});
</script>
HTML for the table part, only a snippet
<td class='votes'>5</td>
<td class='votes'>15</td>
<td class='votes'>25</td>
HTML for the div part, only a snippet of the div:
<div class='popup'>
<ul>
<li>John Johnsson</li>
<li>John Doe</li>
</ul>
</div>
<div class='popup'>
<ul>
<li>Matt Theman</li>
<li>Peter Watley</li>
</ul>
</div>
jsFiddle Demo
You don't have to iterate using each for .click, that will happen internally. You can use .index() to get the index of the element clicked with reference to its parent.
$('.votes').click(function() {
$('.popup').eq($(this).index()).dialog();
});
Initially, the main problem is that you are not using string concatenation to apply the index to the selector (demo):
$('.votes:eq(index)')
// the Sizzle selector engine doesn't know what the string "index" is.
instead of
$('.votes:eq(' + index + ')')
// using concatenation calls the .toString() method of index to apply "0" (or "1", "2", etc.)
// so that the parsed string becomes '.votes:eq(0)' which the Sizzle selector engine understands
Once the Sizzle selector engine understands which elements to target (demo), the second problem is how jQueryUI changes the DOM with the .dialog method.
Inital markup:
<table>
<tbody>
<tr>
<td class="votes">5</td>
<td class="votes">15</td>
<td class="votes">25</td>
</tr>
</tbody>
</table>
<div class="popup">
<ul>
<li>John Johnsson</li>
<li>John Doe</li>
</ul>
</div>
<div class="popup">
<ul>
<li>Matt Theman</li>
<li>Peter Watley</li>
</ul>
</div>
Once the first click event is handled, one of the div.popup elements is transformed into a jQueryUI Dialog and is appended to the body, removing it from its initial position, like so:
<table>
<tbody>
<tr>
<td class="votes">5</td>
<td class="votes">15</td>
<td class="votes">25</td>
</tr>
</tbody>
</table>
<div class="popup">
<ul>
<li>Matt Theman</li>
<li>Peter Watley</li>
</ul>
</div>
<div class="ui-dialog ui-widget ..."> ... </div>
So your initial indexes no longer apply. Fortunately, there are several solutions to both problems (a few of which I've listed below).
Solutions to Problem 1:
Use string concatenation as described above.
Use the .eq method instead, which will accept the index variable as-is
Use a delegate handler instead and grab the index from within the handler:
Example of 2:
$('.votes').eq(index);
Example of 3:
$('table').on('click', '.votes', function (e) {
var vote = $(this),
index = vote.parent().index(vote);
});
Solutions to Problem 2:
Create all of the dialogs initially and open them as needed.
Create the dialogs using a deep clone of the div element. (Not recommended)
Remove the td element to match the removed and re-appended div element. (Not recommended)
Example of 1:
var popups = [];
$('.popup').each(function (i, elem) {
var popup = $(elem).data('index', i).dialog({
"autoOpen": false
});
popups.push(popup)
});
$('table').on('click', '.votes', function (e) {
var vote = $(this),
index = vote.index();
popups[index].dialog('open');
});
I'm sure there are other solutions as well, but these are the ones I thought of of the top of my head.
Functional demo: http://jsfiddle.net/2ChvX/2/
UPDATE:
With your chosen table structure, you're actually looking for the index of the parent tr element as that is what corresponds with the div.popup element. To get the index of the parent tr element, change the line that gets the index from:
index = vote.index();
to:
index = vote.parent().index();
Updated fiddle: http://jsfiddle.net/AZpUQ/1/
Updated
FWIW, here's an example using the jQueryUI dialog (which I presume you are using?) and javascript sectionRowIndex and cellIndex.
Reusable code allowing you to identify the cell the user clicked in and perform appropriate action.
http://jsfiddle.net/KbgcL/1/
HTML:
<table id="myTable">
<tr>
<th>Label:</th>
<th>Washington</th>
<th>Idaho</th>
<th>California</th>
</tr>
<tr>
<td class='label'>Votes</td>
<td class='votes'>5</td>
<td class='votes'>15</td>
<td class='votes'>25</td>
</tr>
<tr>
<td class='label'>Voters</td>
<td class='voters'>5,000</td>
<td class='voters'>15,000</td>
<td class='voters'>25,000</td>
</tr>
</table>
<div id="msg"></div>
jQuery/javascript:
var myTr;
$('#msg').dialog({
autoOpen:false,
title: 'Report:'
});
$('#myTable tr td').click(function() {
myTr = $(this).closest('td').parent()[0].sectionRowIndex;
myCell = this.cellIndex;
myState = $('#myTable').find('tr:eq(0)').find('th:eq(' +myCell+ ')').html();
myVoters = $('#myTable').find('tr:eq(' +myTr+ ')').find('td:eq(' +myCell+ ')').html();
if (myTr==2 && myCell==3){
//California
$('#msg').html('There are ' +myVoters+ ' voters in ' +myState);
$('#msg').dialog('open');
}else if(myTr==1 && myCell==1){
$('#msg').html('There were ' +myVoters+ ' votes made in ' +myState);
$('#msg').dialog('open');
}
});
I have a form with multiple inputs / radio buttons.
I also have a series of Yes & No radio buttons. When the "Yes" radio button is checked, I have some data slide down beneath.
HTML:
<div class="item seperator first clearfix">
<label>test</label>
<div class="radioWrap">
<label class="yes">
<input class="homepageContent" name="homepageContent" type="radio" value="yes" />
</label>
<label class="no">
<input class="homepageContent" name="homepageContent" type="radio" value="no" checked />
</label>
</div>
</div>
<div class="extrasInner">
<div class="item clearfix">
<label for="theContent">Your Content:</label>
<textarea id="theContent" name="theContent"></textarea>
</div>
</div>
<div class="extrasOuter hide clearfix">
Make Changes
<span>Click "Make Changes" to update.</span>
</div>
The jQuery:
$("input:radio[name=homepageContent], input:radio[name=addSocialIcons], input:radio[name=addTracking]").click(function() {
var value = $(this).val();
if (value == 'yes') {
$(this).parent().parent().parent().next().slideDown();
$(this).parent().parent().parent().next().next().slideDown();
} else {
$(this).parent().parent().parent().next().slideUp();
$(this).parent().parent().parent().next().next().slideUp();
}
});
Question 1) This works absolutely fine in Google Chrome, but not in Firefox and IE. It doesn't seem to recognise the click function?
Solved: I had a function within one of my files that removes the value from input fields on focus and this was stripping the value of the radio buttons as well in IE / Firefox (but not chrome!).
Question 2) Is my DOM traversing for the slideUp / slideDown an acceptable way of achieving what I'm trying to do? Are there any disadvantages to how I'm doing it and can it be improved?
Answer to #1
As Anthony Grist pointed out, there doesn't seem to be an issue with the click function.
Answer to #2
Your DOM traversal seem a bit unnecessary. In fact, your DOM structure is in need of rearrangement.
Using a checkbox instead of radio buttons. A checkbox only accepts two values: true or false, or in your case, yes or no. It seems more suitable.
Encapsulate your extras inner and extras outer divs inside your item div instead of having it next to the checkbox. This way, you make it easier to traverse within the item.
Also, you should read up on the different types of traverse functions JQuery has:
.parent() / .parents()
.children()
.closest()
.next()
.prev()
.siblings()
.find()
and many more.
Knowing all of these traverse functions, you'll most likely never ever do parent().parent().parent()... again. :)
Here's a JSFiddle example | Code
HTML
<ul>
<li class='item'>
<label>
<input class="homepageContent" name="homepageContent" type="checkbox" value="yes" />
Item 1
</label>
<div class='extras'>
<div class='inner'>
<label>
Your Content:<textarea name="content"></textarea>
</label>
</div>
<div class='outer'>
Make Changes
<span>Click "Make Changes" to update.</span>
</div>
</div>
</li>
</ul>
Javascript
$("input:checkbox").click(function() {
var $this = $(this),
$item = $(this).closest(".item");
if($this.is(':checked')){
$(".extras", $item).slideDown();
}else{
$(".extras", $item).slideUp();
}
});
CSS
.extras{
display: none;
}
Value of the radio button will always be same, no matter it is checked or not. If you want to know the particular radio button is checked or not then use this code. Based on the status of the radio button do your stuff.
var value = $(this).attr('checked')
That is working for me in FF (jsfiddle), although the DOM looks a little convoluted (I'm guessing because it's missing a lot of your other CSS/resources).
I think you can simplify the jQuery selectors a lot. Generally, using simple ID or class selectors will make the your page much more performant (and simpler!)
$('.homepageContent').click(function() {
var value = $(this).val();
if (value == 'yes') {
$('.extrasInner').slideDown();
$('.extrasOuter').slideDown();
} else {
$('.extrasInner').slideUp();
$('.extrasOuter').slideUp();
}
});
Hopefully doing something like this makes it work cross browser better too.
try this way
$("input:radio[name=homepageContent], input:radio[name=addSocialIcons], input:radio[name=addTracking]").click(function() {
var value = $(this).val();
if (value == 'yes') {
$(this).parents('.seperator').next().slideDown();
$(this).parents('.seperator').next().next().slideDown();
} else {
$(this).parents('.seperator').next().slideUp();
$(this).parents('.seperator').next().next().slideUp();
}
});
EDIT
and also a point
wrap your code inside
$(document).ready(function(){});
like this
$(document).ready(function(){
$("input:radio[name=homepageContent], input:radio[name=addSocialIcons], input:radio[name=addTracking]").click(function() {
var value = $(this).val();
if (value == 'yes') {
$(this).parents('.seperator').next().slideDown();
$(this).parents('.seperator').next().next().slideDown();
} else {
$(this).parents('.seperator').next().slideUp();
$(this).parents('.seperator').next().next().slideUp();
}
});
});
In trying to build a page where I can filter the types of jobs and the offices using the hide/show function, I find that if an element is hidden, then an element underneath the element is "told" to hide, it doesn't actually hide. In other words, hide only works if the actual element is shown.
Here is the code, to duplicate, Hide office 2, then hide developers, then show office 2 again. The developers (which "should" be hidden) display within office 2.
Is there a way around this? It would seem jquery would hide the "sub" elements as well, but it doesn't.
<input type="checkbox" id=office1 name="test" class="link1" />Office 1<BR>
<input type="checkbox" name="office2" checked='true' class="link2"/>Office 2<BR>
<input type="checkbox" name="office3" checked='true' class="link3" />Office 3<BR>
<input type="checkbox" name="developer" checked='true' class="link4" />Developer<BR>
<input type="checkbox" name="receptionist" checked='true' class="link5" />Receptionist<BR>
<input type="checkbox" name="manager" checked='true' class="link6" />Manager<BR>
<table border='1'>
<tr>
<td class="toggle-item-link1"><B>Office 1</B><HR>
<div class="toggle-item-link6"><BR>Manager</div>
<div class="toggle-item-link6"><BR>Manager</div>
<div class="toggle-item-link6"><BR>Manager</div>
</td>
</tr>
<tr >
<td class="toggle-item-link2"><B>Office 2</B><HR>
<div class="toggle-item-link4"><BR>Developer</div>
<div class="toggle-item-link4"><BR>Developer</div>
<div class="toggle-item-link6"><BR>Developer</div>
<div class="toggle-item-link5"><BR>Receptionist</div>
</td>
</tr>
<tr>
<td class="toggle-item-link3"><B>Office 3</B><HR>
<div class="toggle-item-link4"><BR>Developer</div>
<div class="toggle-item-link4"><BR>Developer</div>
<div class="toggle-item-link5"><BR>Receptionist</div>
</td>
</tr>
<td>
</td>
</tr>
</table>
<script>
$(document).ready(function() {
$('[class^=link]').click(function() {
if ($(this).attr("checked")) {
var $this = $(this);
var x = $this.attr("className");
//when 'checked'
$('.toggle-item-' + x).show(1000);
return;
}
//when 'unchecked'
var $this = $(this);
var x = $this.attr("className");
$('.toggle-item-' + x).hide(1000);
});
});
</script>
Since .hide() with an animation speed will only run on visible elements, you can add a case in there for hidden ones as well, like this (a few more optimizations here, just cutting down on code):
$('[class^=link]').click(function() {
var x = $(this).attr("className");
if (this.checked) {
$('.toggle-item-' + x).show(1000);
} else {
$('.toggle-item-' + x).hide(1000).filter(':hidden').hide();
}
});
You can try out a demo here. We're just accounting for the already :hidden elements that won't animate and skipping to them doing a display: none; by calling .hide() without an animation speed.
In addition to the hide()/show(), use a class named hidden, with the CSS:
.hidden {
display: none;
}
When you hide the item, you also add the class hidden. And when you show it, you also remove hidden.
Here's a cleaner and simpler solution:
$("#randomdiv").hide(1000, function() { $(this).css("display", "none"); });
The callback of hide/show in jQuery does fire even if the function itself didn't do its thing due to the parent elements. Using the above method with jQuery, the elements will hide regardless if they are in a hidden parent element or not, while also performing the usual smooth transition if they are shown.