jquery function to show/hide textareas based on which option is selected - javascript

I'm working up a basic survey and one of the questions is a yes/no question. If the user selects no, I'd like to show a textarea below the question for the user to explain his/her reasons for the no answer. If they click yes, the text box remains hidden (or hides if they had clicked no and shown it).
Here is a snippet of my HTML (yes, I'm using tables for formatting :-) . It saves me time in this case). There are 4 yes/no questions. This is just one of them. The only difference among them are the id names (#explain1, #explain2, #explain3, #explain4)
<tr id="yesno1">
<!-- yes/no1 choices --> <!-- Yes(1) No(0) -->
<td class="center"><input name="yn1" value="1" id="yes1" type="radio"></td>
<td class="center"><input name="yn1" value="0" id="no1" type="radio"></td>
<!-- yes/no1 question -->
<td class="question">
Did you meet your goals during this program? (If no, explain.)
</td>
</tr>
<tr class="explain-box" id="explain1">
<td></td>
<td></td>
<td class="explain-text">
<textarea name="explain1" placeholder="Please explain..."></textarea>
</td>
</tr>
And here is my jQuery. This works with question one:
$(function() {
$('.explain-box').hide();
$('#no1').click(function() {
$('#explain1').show();
});
$('#yes1').click(function() {
$('#explain1').hide();
});
});
I'm fairly fuzzy with javascript and jquery, so my question is how can I make the jquery code work without typing out the condition for each and every ID of every yes/no question? I know that I can use this somehow, but I don't know how to go about it. Can someone provide an idea of a function to use in this case? Should I just bite the bullet and type in each question condition since it's only 4 questions?

Try using the starts with selector:
$(function() {
$('.explain-box').hide();
$('[id^=no]').click(function() {
$(this).parents("tr").next(".explain-box").show();
});
$('[id^=yes]').click(function() {
$(this).parents("tr").next(".explain-box").hide();
});
});

You could give the checkboxes a yes or no class, not just an ID.
Then, using the this syntax you could find the textarea associated with it. Something along the lines of:
$(function() {
$('.explain-box').hide();
$('.no').click(function() {
$(this).parents("tr").next().find('.explain-box').show();
});
$('.yes').click(function() {
$(this).parents("tr").next().find('.explain-box').hide();
});
});
EDIT
You could even simplify this further by writing one function to toggle the textarea:
$(function() {
$('.explain-box').hide();
$('.checkbox').click(function() {
var show = $(this).val() == "0";
$(this).parents("tr").next().find('.explain-box').toggle(show);
});
});

Here's how I would do it — without tables or switches.
$('input:radio').on('change', function(){
// compare against string value of input
if ($(this).val() === '0') {
// show textarea closest to $(this)
$(this).closest('div').find('textarea').show();
}
});
Demo

Related

jQuery closest button after input [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I need the name of the next button from the input feald, the button can be in different positions(in table, in div after table, etc.). Like a find next in quelltext.
http://jsfiddle.net/LF6pK/
HTML:
<table>
<tr>
<td>Benutzer:</td>
<td><input type="text" id="Benutzername" name="Benutzername"/></td>
</tr>
<tr>
<td>Passwort:</td>
<td><input type="password" id="Passwort" name="Passwort"/></td>
</tr>
<tr>
<td></td>
<td class="fr"><a href="#info" class="submit" onclick="login()">
<button>Login</button>
</a></td>
</tr>
</table>
JS:
$('input').keypress(function(event){
if(event.which==13){
event.preventDefault();
alert($(this).closest('button').html());
alert($(this).next('button').html());
}
});
The alert is always undefined.
EDIT:
Sure i can give the button a unique id but i have 1 page with 10 buttons and each 10-20 inputs. So i hope a easy way to call always the next and dont give alle buttons a uniqe id and a seperate funktion to all inputs.
EDIT2:
I meen with the name the innerHTML of the button.
EDIT3:
The table is not always around the inputs.
EDIT4:
Better example http://jsfiddle.net/LF6pK/7/ and i prefer a dynamic like next button solution.
Look, the problem is:
.closest() is used to call the closest PARENT.
.next() is used to call the next SIBLING, within the same parent of element.
How you should do it:
Use .closest() to call the CLOSEST PARENT that wraps the <input> AND the <button>.
As i can see in you HTML, the closest parent that wrap both is <table> tag. Then you have to use:
$('input').keypress(function(event){
if(event.which==13){
event.preventDefault();
alert($(this).closest('table').find('button').text());
}
});
Fiddle:
http://jsfiddle.net/LF6pK/5/
UPDATED:
var closest = $(this).closest(':has(button)') will find the closest parent that has a button
.parentsUntil(closest) will call all parents until the closest parent that has a button
.nextAll('button') will call the buttons that comes only next each parents
.first() will filter the first one that comes next
jQuery:
$('input').keypress(function(event){
if(event.which==13){
var closest = $(this).closest(':has(button)')
event.preventDefault();
alert($(this).parentsUntil(closest).nextAll('button').first().text());
}
});
Fiddle:
http://jsfiddle.net/LF6pK/9/
UPDATED [2]:
$('input').keypress(function(event){
if(event.which==13){
var closest = $(this).closest(':has(button)')
event.preventDefault();
if($(this).parentsUntil(closest).nextAll('button').length >= 1){
alert($(this).parentsUntil(closest).nextAll('button').first().text());
} else {
alert($(this).parentsUntil(closest).nextAll().find('button').first().text());
}
}
});
Fiddle:
http://jsfiddle.net/LF6pK/11/
It will give you text of the button.
$(this).parents().find('button').text()
OR
$(this).closest('table').find('button').text()
You have to make sure that every button has same wrapper class (no need to be direct parent).
<table class='wrapper'>
...
<tr>
<td>
<button></button>
</td>
</table>
<div class='wrapper'>
<input type='text'>
<button></button>
</div>
Then you can access it by this:
$('input').keypress(function(event){
if(event.which==13){
var button = $(this).closest('.wrapper').find('button');
event.preventDefault();
alert(button.text());
alert(button.text());
}
});
alert($(this).offsetParent().find('button').html());
http://jsfiddle.net/LF6pK/4/
Just position the element with relative or however you wish.
Have you considered using forms if you are just trying to perform an action on enter key press?
<form>
<table>
<tr>
<td>Benutzer:</td>
<td><input type="text" id="Benutzername" name="Benutzername"/></td>
</tr>
<tr>
<td>Passwort:</td>
<td><input type="password" id="Passwort" name="Passwort"/></td>
</tr>
<tr>
<td></td>
<td class="fr"><button>Login</button></td>
</tr>
</table>
</form>
<script>
$('body').on('submit','form',function(e) {
e.preventDefault();
// Do whatever with the inputs
});
</script>

Select all table rows between headers using JQuery

Having the following automatically generated table layout (I have nearly no influence over it)
<table>
<tr>
<th>First Header</th>
<th>
show/hide
</th>
</tr>
<tr>
<td>A question?</td>
<td><input value="User's answer" /></td>
</tr>
<!-- Some more rows -->
<tr>
<th>Second Header</th>
</tr>
<!-- Some more question blocks -->
</table>
... I'd like to select all the <tr>-elements between two headers using Javascript/jQuery
in order to provide such features like:
Hiding all the questions belonging to a certain header.
Automatically edit the <input>s (eg. check/uncheck all or restore default)
The links causing the desired actions are already in the correct headers.
What would be the best way to approach this issue?
You can use nextUntil() to solve this problem.
function getRows(start){
return start.nextUntil(function(i, v){
return $('th', v).length > 0;
});
}
Demo: Fiddle
Implementation of Show/Hide
$('table').on('click', '.used-for-some-action', function(){
getRows($(this).closest('tr')).toggle();
return false;
});
Demo: Fiddle
Update:
Based on comments by #BLSully
$('table').on('click', '.used-for-some-action', function(){
$(this).closest('tr').nextUntil('tr:has(th)').toggle();
return false;
});
Demo: Fiddle
I like Arun P Johny's answer. Here's what I originally thought (this code implements the hide/show functionality)
$(".used-for-some-action").click(function(e) {
e.preventDefault()
$(this).parents("tr").next().is(":visible") ? $(this).parents("tr").next().hide() : $(this).parents("tr").next().show();
});
Fiddle: http://jsfiddle.net/DQMht/1/
I would keep it real simple. You're using JavaScript, so when the page loads, just add a class to rows with a <th>, then use the class.
$(function() {
$("th").parent().addClass("hasTH");
});
Then you can simply target rows that have the hasTH class.
Another option would be to still do it when the page loads, but instead of adding a class, group the rows into new <tbody> elements. This would give you the most pure DOM representation.
Try this:
$("tr:has(th)").each(function(){
if ($(this).find('th').length==2) {
// here you have this: that represent the row which have two td
}
})

jQuery detects which element is visable

I have several tables with similar class names, but only one table is visible at a time. I am having troubles of using jQuery to detect and save the class name of the visible table (I can use .is(':visible') to check and save the class name of the positive ones, but it is kind of cumbersome.). I appreciate any suggestions.
HTML
<table class="tab_Chemical" border="0" style="display:none">
<tr><th><label for="id_wat_hl">Water Column Half life (days):</label></th>
<td><input type="text" name="wat_hl" id="id_wat_hl" /></td></tr>
</table>
<table class="tab_Physical" border="0">
<tr><th><label for="id_mas_tras_cof">Mass Transfer Coefficient (m/s):</label></th>
<td><input type="text" name="mas_tras_cof" value="1e-08" id="id_mas_tras_cof" /></td></tr>
</table>
JS
<script type="text/javascript">
$(document).ready(function() {
###CODE TO DETECT VISIBLE CLASS and SAVE the CLASS NAME###
});
</script>
Try using the :visible pseudo-selector, along with the ^ (starts with) selector:
$(document).ready(function () {
var visible = $("[class^='tab_']:visible");
});
But the starts with selector is a little fuzzy. If you can, give them all a common class (Good shout Kevin B)(the below assumes the class tab is the common class):
$(document).ready(function () {
var visible = $(".tab:visible");
});
Something like this maybe:
var classes=[];
$("table:visible").each(function(){
classes.push($(this).attr('class'));
});
Seems like an odd requirement though. You might want to take a step back and see if there is a more logical way to do what you want.

JQuery .on only firing once on dynamically generated elements

So I have the following problem. I am trying to add a two events to a table of checkboxes.
Here's an example of the html.
<body>
<div id='container'> //static element, everything beyond this element is dynamic
<div id='pane_x'>
<div id='bottom_x'>
<div id='bottom_left_x'>
<div id='results_x'>
<div id='list_x'>
<div id='table_1'>
<table>
<tbody>
<tr>
<td>
<input type='checkbox' name='blah' id='blah_obj.id_x' class='blahblah'>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
I am trying to select the checkboxes only hopefully by using a prefix selector [id^='blah_']. I am able to get the code working for the first pane ie: pane_0, but it doesn't fire on pane_1 or beyond.
jquery(document).on("change", "[id^='blah_" + obj.id + "']", function() {
//code here
});
There may be nesting errors as I just made an approximate estimate of the html. The weird thing is I can see them by using a daisy chained .children() statement, but I can't select the input elements.
Since the comments don't support the same code blocks as this section I'll just add it here:
jquery(document).on("change", ".checked", function() {
var ids = jquery(this).attr("id").split("_");
if (ids[0] === "blah")
//do code
}
});
edited the id for clarity. The id structure is "blah_" obj.id "_" individual iterator. So 3 checkboxes on pane 0 would look like this:
blah_0_0
blah_0_1
blah_0_2
there are 2 other sets of checkbox lists on this page that I do not want to target with these functions, that is why i'm using the prefix selector.
The point of using startsWith selector is not to try to complete the whole value as you are doing with obj.id if obj.id is even defined.
Following would find all input with ID's starting with 'blah_' either existing or in the future.
jQuery(document).on("change", "input[id^='blah_']", function() {
//code here
});
Using the class as selector makes even more sense if they all share a common class
jQuery(document).on("change", "input.blahblah", function() {
//code here
});
Also note you have typo in jquery should be jQuery unless you have defined it otherwise in your own code
Important note ID's may not be repeated in a page, in case you have been repeating the same checkbox ID. They must be unique by definition
here another sample :
$("body").on({
click:function(){
// where $(this) is the current item changed
}
}, "input.blahblah");
​

How do I select a collection of checkboxes...?

I have the html:
<tr>
<td><input type="checkbox" value="3" id="userListingSelect0" cssclass="cbDelete">
</td><td>general</td>
<td>Edit</td>
</tr>
<tr>
<td><input type="checkbox" value="1" id="userListingSelect1" disabled="disabled" cssclass="cbDelete">
</td><td>hmladmin</td>
<td>Edit</td>
</tr>
And im trying to use jQuery to get all of the checkboxes.
Im using:
console.log(jQuery('.cbDelete').html());
But all im getting is undefined. How do I...
1) Get all the elements
2) Iterate through them?
I tried using:
jQuery('.cbDelete').each(function () {
console.log('got here');
if (this.checked) {
selectionMade = true;
}
resultsGot = true;
});
And still it didn't get to to the 'got here' line so it looks like I cant get to collection. Not sure why....
The reason why this line doesn't work is because of the cssclass attribute
console.log(jQuery('.cbDelete').html());
Changing it to class will make this work. Or the answer from Igor.
jQuery class selector works when class attribute is defined, but you have cssclass. So in your case you may try:
$("input[cssclass='cbDelete']");
To iterate through just use each as usual.
You're using a non-standard identifier to give the checkbox a class. Change cssclass to class and then $('.cbDelete') will work; the . (dot) means "class".
As #Igor Dymov says rather abruptly in his answer, using
$("input[cssclass='cbDelete']");
works; this finds any input with the custom attribute cssclass, with a value of cbDelete.
Personally, I'd use a class as it's cleaner, validates well and the selector is simpler (and possibly a bit faster).
$("input:checkbox").each(function(){
console.log('got here');
if (this.checked) {
selectionMade = true;
}
resultsGot = true;
});
If you want to retrieve only those checkbox inside your specified table(let's say your table's id is "table_a"), it will be
$("#table_a input:checkbox").each(function(){
Yeah if the cssClass is just changed to class it works. So your view does not change the cssClass to class? Or was that in source? Some people gave you already answer for if you are using the cssClass in source.
If you are defining that in asp:
<asp:TextBox id="TextBox1" ForeColor="Red" CssClass="class1" />
should render to
<input type=text class="class1" style="ForeColor:red">
http://jsfiddle.net/SdHuK/

Categories

Resources