I have a table with few rows. Each rows has header, data and hidden field. Data column can have either text or textarea.
<table id="knowledgeTreeTable" class="custom">
<tbody>
....................
<tr>
<th class="">What is the name of the party?</th>
<td class="">
<textarea id="ktField_7" class="ktEdit" type="text"></textarea>
</td>
<input id="ktField_7H" type="hidden" value="Unique contested">
</tr>
<tr>
<th class="">What is the name of the opposing party?</th>
<td class="">
<input id="ktField_8" class="ktEdit" type="text" style="width: 97%;">
</td>
<input id="ktField_8H" type="hidden" value="Query">
</tr>
......................
</tbody>
</table>
I am able to read the content of header and hidden field but not sure how to read data column as it can have two different types of element.
$("#knowledgeTreeTable tr").each(function() {
alert($('th', this).text());//OK
//alert($('td > [input, textarea]', this).val()); // This is not OK.
alert($('input', this).val());//OK
});
You can't group selectors like
td > [input, textarea]
Instead, use
td > input, td > textarea
Just as you would in a CSS selector, look for both:
alert($('td > input, td > textarea', this).val());
Although since you're using the same class for both, I'd be inclined to use:
alert($('td > .ktEdit', this).val());
Whenever you're trying to access a child element in a loop like this, you need to establish what the common factors between each element is. In this case they are different tags with different names, but they both have the ktEdit class, and both have type="text" (which I don't believe is actually applicable to textareas).
In this case, the common variable is the class name, so you can use that as your selector. As long as you target your parent loop correctly, it won't matter if you use that class on other elements throughout the page:
$("#knowledgeTreeTable tr").each(function() {
alert($('.ktEdit', this).val());
});
Related
I want to show and hide several tables on one page with one button. Unfortunately my script can only show and hide one table at a time.
I have a page with a lot of queries. There are also text fields in a table. For a better overview, the tables with the text fields should only be displayed when the checkbox is ticked. The checkbox should not be clicked at the beginning.
function Displayer(n)
{
var check = document.getElementById('Section'+n);
if (check.style.display == 'none')
{
check.style.display='inline';
}
else
{
check.style.display='none';
}
}
<p><input type="checkbox" class="btnstylega" onClick="Displayer(99)" />Show Tables</p>
<table id="Section99" style="display:none;"> <td>
AAAAAAAAAAAAAA
</td></table>
<table id="Section99" style="display:none;"> <td>
BBBBBBBBBBBBBBB
</td></table><br>
I want to show and hide many tables without adjusting the tables by clicking on the checkbox.
An ID must be unique in a document. The tool to mark multiple elements as part of a group is a class.
Replace your id attributes with class attributes.
Then replace getElementById with getElementsByClassName (or querySelectorAll).
These methods return lists of nodes and not single elements, so loop over the result like an array and access the style property on each one in turn.
The attribute id must be unique in a document, you can use class instead. You can use querySelectorAll() to target all the elements having the class, then loop through them to set the style. You can toggle the class using classList.toggle() like the following way:
function Displayer()
{
var check = document.querySelectorAll('.Section99');
check.forEach(function(table){
table.classList.toggle('show');
});
}
.Section99{
display: none;
}
.show{
display: block;
}
<p><input type="checkbox" class="btnstylega" onClick="Displayer()" />Show Tables</p>
<table class="Section99" class="hide"> <td>
AAAAAAAAAAAAAA
</td></table>
<table class="Section99" class="hide"> <td>
BBBBBBBBBBBBBBB
</td></table><br>
Improvement: It will add the event handler and trigger the change on load where needed
Note the data-attribute on the checkbox
var chg = new Event('change');
document.querySelectorAll(".btnstylega").forEach(function(but) {
but.addEventListener("change", function() {
var checked = this.checked,
section = this.getAttribute("data-tables");
document.querySelectorAll('.Section' + section).forEach(function(sect) {
sect.classList.toggle("hide",!checked);
});
})
but.dispatchEvent(chg);
});
.hide {
display: none;
}
<p><input type="checkbox" class="btnstylega" data-tables="88" checked />Show Tables 88 </p>
<p><input type="checkbox" class="btnstylega" data-tables="99" />Show Tables 99</p>
<table class="Section88">
<tr>
<td>
AAAAAAAAAAAAAA
</td>
</tr>
</table>
<table class="Section88">
<tr>
<td>
BBBBBBBBBBBBBBB
</td>
</tr>
</table><hr>
<table class="Section99">
<tr>
<td>
CCCCCCCCCCCCCCCC
</td>
</tr>
</table>
<table class="Section99">
<tr>
<td>
DDDDDDDDDDDDDDDDDDDD
</td>
</tr>
</table>
I have a table which contains a combination of plain text, input textboxes, selects, and spans. I need to iterate through the table row by row and pull out the value in each cell. Within my table all <tr> have a particular css class.
$(".gridBody").each(function(rowindex){
$(this).find("td").each(function(cellIndex){
var cell = $(this).first()
})
In my debugger I can see what kind of object is being returned by $(this).first() but I can't find out how to get into its attributes. I have tried using jqueries html parser to turn it back into a dom element, but instead of getting, for example, a textbox, I get something like [[html inputtextbox]]. Most of the methods that work on regular dom elements are not working for me.
If I use $(this)[0].innerText it returns the correct value when the contents of the cell are plain text, but not when they are a form of input or nested in a span element. What I would really like to be able to do is get a regular html dom element back that I can then check the type of with $.is() and then vary much logic from there.
How do I get the first child element in a table cell as an html dom element that I can manipulate with jquery like any other dom element?
var collected = $("#myTable td").find("input, textarea, span").map(function(){
return this.value || this.textContent;
}).get();
console.log( collected ); // an array holding values or text
http://jsbin.com/zewixe/2/edit?html,css,js,console,output
If you want only the immediate children than use the right > selector
(">input, >textarea, >span")
Heres how I would do it:
<table>
<tr>
<td>
<h1>Some stuff.</h1>
</td>
</tr>
<tr>
<td>
<input type="text" value="1"/>
</td>
<td>
<input type="text" value="2"/>
</td>
</tr>
<tr>
<td>
<input type="text" value="3"/>
</td>
</tr>
<tr>
<td>
<input type="text" value="4"/>
</td>
</tr>
</table>
$(function() {
function getFormData(selector){
'use strict';
var formTypes = {
text: 'text',
radio: 'radio',
select: 'select'
},
values = [];
$(selector).children().each(function(idx, childNode) {
if (childNode.getAttribute('type') && formTypes[childNode.getAttribute('type')]) values.push(childNode.value);
});
return values;
}
alert(
getFormData('table tr td.someClass')
);
})();
http://codepen.io/nicholasabrams/pen/RaKGjZ
I have the following html which is basically a parent table with some child tables inside it,
<table id="roottable" class="tablemain" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td></td>
<td>
<table class="intable" align="center" border="0">
<tbody>
<tr>
<td class="chn" colspan="2" align="center">
<div>
<div class="mparent">
<div class="checkbox">
<input type="checkbox" id="ch243" name="ch243" value="243">
<label for="ch243"></label>
</div>
<div class="chtext">Category</div>
</div>
</div>
</td>
</tr>
<tr>
<td>Param two</td>
<td>
<div class="checkbox">
<input type="checkbox" id="ch244" name="ch244" value="244">
<label for="ch244"></label>
</div>
</td>
</tr>
</tbody>
</table>
......
......
<table class="intable" align="center" border="0">
......
......
What I need to do is access all checkboxes of the nested table, for each table. That is get the checkboxes inside the first nested table, perform some operations with it, move to the next nested table do the same with the checkboxes inside it.
I can access individual tables like below with their id,
$('#tableid').find('input[type="checkbox"]').each(function () {
});
This works, but the tables are auto generated from db and the id is not known beforehand, also, the number of tables may vary, so I have no option other than selecting the parent table and then look for every child tables inside it one by one ... I have tried this ...
$('table').each(function(){
$(this).find('input[type="checkbox"]').each(function () {
// DO STUFFS WITH CHECKBOXES
});
But it doesn't work... How do I go about this? Thanks.
$('table tr td').each(function(){ // this line is for main outer table
$(this).children('table').each(function () { //this will iterate all the child table
$(this).find('input:checkbox').each(function(){ //this will find checkbox inside each table
//Your Stuff
});
});
});
NOTE :- I m not using id selector here because questioner mentioned that he doesn't know id's beforehand.
Working Demo
Working Demo
Your final code block looks acceptable, except that you haven't prevented the table selector from also selecting the outer table. As written, this would cause each set of checkboxes to be considered twice - once as part of its own table and again (actually first) as descendants of the outer table.
Try a more specific selector:
$('#roottable .intable').each(...)
I would do something like this:
$('#roottable').find('.intable').each(function(index, elt) {
// operate now on each "child table"
var $childTable = $(elt);
$childTable.find('input[type="checkbox"]').each(function(i, cb){
// Do your stuff with the checkoxes of the current ".intable" table
});
});
Just use:
var tableInputs = {};
$('#roottable input[type="checkbox"]').each(function () {
var id = $(this).closest('table').attr('id');
var name = $(this).attr('name');
tableInputs[id] = {};
tableInputs[id][name] = $(this).val();
});
This will select all checkboxes that are a child of a table.
EDIT if you need to group just find the id of the closest parent table and use that as an index for an object. You end up with one large object with all the id's as properties, while using only one each loop.
I have a tbody inside which there are href/input type text/ etc
I have a code to get all elements of tbody but how to disable it.
My tbody
<tbody id="FamilyHistory_3">
<tr>
<td class="tablecell">
<a id="FamilyHistory_3" name="316098" value="316098" onclick="javascript:save('FamilyHistory_3','test');" href="#">
<img style="border-style: none" src="../images/v10/arrow_doc.png">
</a> test
</td>
</tr>
<tr>
<td>
<table>
<tbody>
<tr>
<td></td>
<td class="tablecell">
<input type="checkbox" value="Yes" name="10627_316098">Yes
<input type="checkbox" checked="" value="No" name="10627_316098">No
</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td height="2px"></td>
</tr>
</tbody>
Below is my code to get the content of tbody
function save(inputID,category){
var content= document.querySelectorAll('#tbodyID');
for(var i=0; i<content.length; i++){
// how to disable all the elements inside it
}
}
JSFiddle
document.querySelector('#tbodyID input').disabled = true;
You don't need jQuery for this.
For more than one:
JSFiddle
var l = document.querySelectorAll('#tbodyID input');
for (i = 0;i<l.length;i++)
{
l[i].disabled = true;
}
There's no need to loop, jquery can deal with groups of elements just using selectors.
Use the Jquery selectors and the prop function to add disabled="disabled" to each one.
You can also select multiple items using a comma separated list
$('#tbodyID input, #tbodyID select, ....').prop('disabled', true);
disabling an a tag will not prevent it from being clicked though. May be better to hide() these.
$('#tbodyID a').hide();
You might need to specify the types of all elements you want to disable. If you have jQuery, you can do that with something like this:
$('#tbodyID').find('a, input').prop('disabled', true);
Explanation
$('#tbodyID') : Select the element with id tbodyID
find('a, input') : Find all the a and input elements inside it
prop('disabled', true) : Set the disabled property of each element returned by the previous command
Based on your answer finally I accomplished my task using below code. I know you people have already answer but then also I am posting my answer with few addition.
Disable input
$('[id='+inputID+']').find('input').attr('disabled', true);
id of tbody
Disable click but clickable hand will be there but no request will be submitted to server
$('[id='+inputID+']').attr('onclick','').unbind('click');
id of anchor tag
Thanks,Pise
Let me explain:
I have a table form and some fields are required and I am trying to create custom validation.
example:
<table>
<tr>
<td class="required">Description</td>
<td>
<input id="input1" />
</td>
<td>Phone</td>
<td>
<input id="input2" />
</td>
</tr>
<tr>
<td class="required">Location</td>
<td>
<select id="select1"/>
</td>
<td>Email</td>
<td>
<input id="input3"/>
</td>
</tr>
</table>
What I wanna do is find all elements with class required
which is pretty easy using:
var requiredElements = document.querySelectorAll(".required");
And then I want to find their closest control element and check if it's value is empty. The problem is I don't know if it's gonna be input or select. I was thinking of using the .closest() function but it could lead to unwanted results if two different inputs are equally close to a required (like in the example above).
Any help would be much appreciated.
You can select a control regardless of type with jQuery by using any one of a number of selectors and combining it with one or more additional selectors.
In the code snippet you provide, the controls you want to select (input1 and select1) are child elements of a table cell element that is a sibling of the cell with the class "required", so we can build a selection thus:
$(".required + td").child
which breaks down as:
Find the elements with the "required" class applied to them.
This will give us the 2 table cells:
<td class="required">Description</td>
and
<td class="required">Location</td>
For each element returned by 1. use the "next adjacent" selector + with td to get the next table cell:
<td><input id="input1" /></td>
and
<td><select id="select1" /></td>
For each element returned by 2. get the child element:
<input id="input1" />
and
<select id="select1" />
There is also a jsFiddle to illustrate actions on the targets (change border to dark red).
Edit
This works because the layout in your snippet consistently places the elements you want to target in the same position relative to the element with your selection criteria. You must have some consistent way of finding elements that are not marked with a class/id otherwise you can't achieve your objective.
Although I like Raad's answer I'd like to post this answer to say what I did to solve my problem.
First of all I added a custom attribute labelFor to every label td with value equal to the id of it's corresponding input as follows:
<table>
<tr>
<td class="required" labelFor="input1">Description</td>
<td>
<input id="input1" />
</td>
<td labelFor="input2">Phone</td>
<td>
<input id="input2" />
</td>
</tr>
<tr>
<td class="required" labelFor="select1">Location</td>
<td>
<select id="select1"/>
</td>
<td labelFor="input3">Email</td>
<td>
<input id="input3"/>
</td>
</tr>
</table>
Then I used the following Validation function:
function validateForm () {
var self = this;
var validationPassed = true;
//First I will gather every .required element in an Array
var requiredTags = document.querySelectorAll(".required");
//Then I will loop through the array
for (var i = 0; i < requiredTags.length; i++) {
//Get value of attribute "labelFor" which would be the controlId that this label refers to
var controlId = $(requiredTags[i]).attr("labelFor");
//Then I use this to check if that control's value is empty.
if ($("#" + controlId).val() == ('' || null)) {
validationPassed = false;
}
}
if (!validationPassed) {
alert("Please fill all the required fields");
}
return validationPassed;
}
This way I check if all required fields are not empty and return true, or return false and an alert to warn user.
I find that the problem Raad described in his Edit is the main reason why this approach could be more useful. You don't have to worry if your input element is always in the same position relatively to your label td element.