I'm trying to dynamically hide/unhide multiple table rows using Javascript to mimic collapse/expand. here are relevant code snippets:
function selectionFilter(check, filter){
var elem = document.getElementById('myScrollTable').rows;
for(i = 0; i < elem.length; i++){
var type = elem[i].getAttribute('type');
if(type== filter){
if(check == true){
elem[i].style.display='';
}else{
elem[i].style.display='none';
}
}
}
}
and here is the sample HTML:
<input type="checkbox" checked="true" value="t1" onclick="selectionFilter(this.checked, this.value);">some type 1</input >
<input type="checkbox" value="t2" onclick="selectionFilter(this.checked, this.value);">some type 2</input ><br><br>
<table cellspacing="1" cellpadding="2" class="" id="myScrollTable">
<thead>
<tr>
<th>Data1</th>
<th>Data2</th>
</tr>
</thead>
<tbody>
<tr type="t1">
<td rowspan="50">something1</td><td>something2</td>
</tr>
<tr type="t1">
<td>something2</td>
</tr>
.
.
<tr type="t2" style="display:none;">
<td rowspan="50">something1</td><td>something2</td>
</tr>
<tr type="t2" style="display:none;">
<td>something2</td>
</tr>
.
.
</tbody>
</table>
In Firefox everything is fine. However in IE, after the first time any row is hidden, when it is unhidden it has some extra space appending at the bottom. This does not happen when rowspan is not used. I tried many things but couldn't get rid of the extra space.
I would truly appreciate if anyone could give me some hint.
Did you try using block instead of an empty string?
you should try using
elem[i].style.display = 'block';
and if this fails you should try
elem[i].style.display = 'table-row';
and allways you should check the w3schools documentation, its really usefull
http://www.w3schools.com/css/pr_class_display.asp
tellme if this works for you
Related
I have tried finding a solution to my problem for few days already - somehow I just don't manage to find a working solution.
Unfortunately I cannot give the URL for the webpage that I have as it would require a login and password - which I cannot share.
I have the VBA code already doing me everything, login into the webpage - proving the proper information inside the page and clicking validate button. But the problem is that I should then see if the below text appears:
ENQUADRAMENTO EM VIGOR - if yes, I will continue slightly differently the process and if not then differently.
Now below is the code from the webpage:
<tr>
<td>
<table cellpadding="4" border="0" width="100%">
<tbody><tr>
<td class="fieldTitleBold" style="width=30%">Enquadramento em IVA</td>
<td class="fieldValue" colspan="3">NORMAL TRIMESTRAL</td>
</tr>
<tr>
<td style="width=10%" class="fieldTitleBold">Situação</td>
<td class="fieldValue" colspan="3">ENQUADRAMENTO EM VIGOR</td>
</tr>
</tbody></table>
</td>
</tr>
I have tried many different ways and the latest I tried is with byclassname (this worked for me in a different website for similar purpose) but doesn't work here for some reason:
Set doc = ie.document
Set htmTable = doc.getElementsByClassName("ENQUADRAMENTO EM VIGOR")(0)
If Not htmTable Is Nothing Then
'continue depending if the text was found or not in different ways
ENQUADRAMENTO EM VIGOR is the .innerText value not the class name. The class value is fieldValue and is associated with a td (table cell) element.
This is pretty easy if it only occurs once. Use Instr to see if present in page html
If Instr(ie.document.body.innerHTML,"ENQUADRAMENTO EM VIGOR") > 0 Then
Otherwise, you can gather a nodeList of td elements with that class name and loop testing the .innerText
Dim classes As Object, i As Long
Set classes = ie.document.querySelectorAll("td.fieldValue")
For i = 0 To classes.Length - 1
If classes.item(i).innerText = "ENQUADRAMENTO EM VIGOR" Then
'do something
'Exit For ....
End If
End Sub
$(document).ready(function() {
var lenfV = document.querySelectorAll(".fieldValue");
for(let i=0;i<lenfV.length;i++) {
if(lenfV[i].innerHTML == "ENQUADRAMENTO EM VIGOR") {
console.log("is there");
}
//else {console.log(213423);}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p> I think, The below option will help you</p>
<table>
<tr>
<td>
<table cellpadding="4" border="0" width="100%">
<tbody><tr>
<td class="fieldTitleBold" style="width=30%">Enquadramento em IVA</td>
<td class="fieldValue" colspan="3">NORMAL TRIMESTRAL</td>
</tr>
<tr>
<td style="width=10%" class="fieldTitleBold">Situação</td>
<td class="fieldValue" colspan="3">ENQUADRAMENTO EM VIGOR</td>
</tr>
</table>
</td>
</tr>
</table>
I need a XPath expression that count all the <tr> rows that have a starting class attribute string: room_loop_counter grouped by their attribute name itself.
I have the following sample HTML code to extract data from:
<tbody id="container" >
<tr class="room_loop_counter1 maintr">
<td class="legibility " rowspan="6"></td>
<td colspan="4" style="padding:0;"></td>
</tr>
<tr class="room_loop_counter1">
<td ></td>
<td class=""></td>
</tr>
<tr class="room_loop_counter1"></tr>
<tr class="room_loop_counter2 maintr divider"></tr>
<tr class="room_loop_counter2"></tr>
<tr class="room_loop_counter3 maintr divider"></tr>
<tr class="room_loop_counter3"></tr>
<tr class="room_loop_counter3"></tr>
<tr class="room_loop_counter3"></tr>
<tr class="room_loop_counter3"></tr>
</tbody>
Given the above HTML I would want to get as result : 2,1,4. The count is the number of elements minus one, since I want to discard from the count the first <tr>(the one with the maintr) that is the header...
Between <tr> elements there could be other <tr> elements so their are not strictly one after the other, so we can't rely on following or preceding sibling logic.
I've tried with the following XPath expression :
count(//table[#id="maxotel_rooms"]/tbody/tr[#class=distinct-values(//table[#id="maxotel_rooms"]/tbody/tr[starts-with(#class, "room_loop_counter") and not(contains(#class, "maintr"))]/#class)]/#class])
but it doesn't work on chrome(evaluating it with $x('') on the console window) since it doesn't recognize the distinct-values function.
Could you suggest a possible solution? What is the best approach ?
Check this XPath for unique tr with class starts with some data and not followed by some other class name.
//tbody/tr[starts-with(#class, "room_loop_counter") and not(contains(#class, "maintr"))]/following::tr[not(./#class=following::tr/#class) and not(contains(#class, "maintr"))]
Javascript:
var path = "//body/div";
var uniquePathCount = window.document.evaluate('count(' + path + ')', window.document, null, 0, null);
console.log( uniquePathCount );
console.log( uniquePathCount.numberValue );
Ouput:
<tr class="room_loop_counter1"/>
<tr class="room_loop_counter2"/>
<tr class="room_loop_counter3"/>
Is there any way to fill the empty <td></td>, if data does not exist in this?
<table><tr><td></td><td>1</td><td></td></tr></table>
Change it to:
<table><tr><td>Not Data</td><td>1</td><td>No Data</td></tr></table>
Not with HTML itself.
Usually you would do this by generating the HTML using a data in a programming language and a template, with template logic used to insert a default value if none came from the data.
A little bit hackish, because it changes only visual aspect. You can do that with CSS:
table, td {border: 1px solid black; padding: 4px; border-collapse: collapse}
td:empty::before {content: "No Data"}
<table>
<tr>
<td></td>
<td>Real data</td>
<td></td>
</tr>
</table>
Won't really work just with html.
it depends on how you build your HTML-DOM. If it is just a pure HTML-file (*.html ) you could check for value by adding some JavaScrit/JQuery.
But if you are trying to do this, make sure to give your table/tr or td to give element-ids.
<table>
<tr id="1">
<td id="1_1"></td>
<td id="1_2">1</td>
<td id="1_3"></td>
</tr>
</table>
<script type="text">
/* For the amount of rows */
for(var outeri = 1; outeri <= 1; outeri++)
{
/* For the amount of columns */
for(var ineri = 1; ineri <= 3; ineri)
{
var innertd = String(outeri + '_' + ineri);
if(document.getElementById(inntertd).innerHTML == '')
{
document.getElementById(inntertd).innerHTML = 'No Data';
}
else {continue;}
}
}
</script>
This example is not very realistic and more likely not to be done unless your table is just static.
you can add an empty space:
This can be achieved in many ways, here are 2 (c# and jquery)
Solutions:
c#:
Use razor as in the following:
<table>
<thead>
<tr>
<td>Name</td>
<td>Date</td>
</tr>
</thead>
<tbody>
<tr>
#{
if(data)
{
<td>#data.name</td>
<td>#data.date</td>
}
else
{
<td colspan="2">NO DATA</td>
}
}
</tr>
</tbody>
</table>
jQuery:
Select the table and change the html depending on if there is any data
$(document).ready(function()
{
var table = $("table-selector");
var isData = $("data-selector").length;
if(!isData){
table.html("customize HTML right here, considering 'colspan' in case
there is a headers row as well")
}
});
I have a HTML table with a checkbox in one of the columns. I want to know how I could get the row data when the user clicks on the checkbox with javascript (without jquery)? Can anyone please help me with this?
Thanks
HTML DOM solves your problem
<script type="text/javascript">
function getRow(n) {
var row = n.parentNode.parentNode;
var cols = row.getElementsByTagName("td");
var i=0;
while (i < cols.length) {
alert(cols[i].textContent);
i++;
}
}
</script>
<table>
<tr>
<td><input type="checkbox" onclick="getRow(this)" /></td>
<td>aaa</td>
<td>bbb</td>
</tr>
<tr>
<td><input type="checkbox" onclick="getRow(this)" /></td>
<td>ccc</td>
<td>ddd</td>
</tr>
<tr>
<td><input type="checkbox" onclick="getRow(this)" /></td>
<td>eee</td>
<td>fff</td>
</tr>
</table>
EDIT:
this script will help you more, I think:
function getRow(n) {
var row = n.parentNode.parentNode;
var cols = row.getElementsByTagName("td");
var i = 0;
while (i < cols.length) {
var val = cols[i].childNodes[0].nodeValue;
if (val != null) {
alert(val);
}
i++;
}
}
You could try something like this:
HTML:
<table>
<thead>
<tr><th></th><th>Row Text</th></tr>
</thead>
<tr>
<td><input type="checkbox" /></td>
<td>Test</td>
</tr>
<tr>
<td><input type="checkbox" /></td>
<td>Test 2</td>
</tr>
<tr>
<td><input type="checkbox" /></td>
<td>Test 3</td>
</tr>
</table>
JavaScript:
checkboxes = document.getElementsByTagName("input");
for (var i = 0; i < checkboxes.length; i++) {
var checkbox = checkboxes[i];
checkbox.onclick = function() {
var currentRow = this.parentNode.parentNode;
var secondColumn = currentRow.getElementsByTagName("td")[1];
alert("My text is: " + secondColumn.textContent );
};
}
JSFiddle: http://jsfiddle.net/markwylde/wzPHF/1/
if your select is in td directly, try the following:
sel.onclick = function(){
row = this.parentNode.parentNode
//then what you need
}
Note that first you have to find sel with either document.getElementById() or document.getElementsByTagName()
Also you may need to handle onchange event instead of onclick
This will give you content of row directly(all td in tr)
HTML:
<table>
<tr id="tr1">
<td>
<input type="checkbox" value="chkbox1" id="chk1">
</td>
<td>
Lorem ipsum text
</td>
</tr>
<tr id="tr2">
<td>
<input type="checkbox" value="chkbox2" id="chk2">
</td>
<td>
Lorem ipsum text
</td>
</tr>
</table>
Jquery:
$(document).ready(function(){
$('#chk1, #chk2').on('change',function(){
if($('#chk1').prop('checked') || $('#chk2').prop('checked'))
{
var ids=$(this).parent().parent().html();
alert(ids);
}
else
{
}
});
})
if you're new :
onChange EVENT of the checkbox will call the function that i named "checking"
it will send "This.checked", which means, will send True or false to the function "checking", Then i go in the function get that True or False that was sent, and put it in a variable i called "temp".
HTML: onchange="checking(this.checked)" <--- sending out : "This.checked" ( This = the object that creates the Event onchange, and .checked, is the propriety)
you could even send multiple info like this : onchange="checking(this.checked,this.id)" and so on.
JAVASCRIPT :function checking(temp) <--- this is how it gets the "this.checked" in HTML, and put it in the variable temp.
to receive multiple infos : function checking(temp,temp2) and so on.(name it like you want)
then i run a 'IF' with the variable "temp" and if the value of it = true, then do alert.
Hope it helps, think about it and work it so it fits what you need !
HTML :
<table>
<tr>
<td>
<input type="checkbox" value=""onchange="checking(this.checked)">
</td>
<td>
<label>Something Here</label>
</td>
</tr>
</table>
JAVASCRIPT :
function checking(temp)
{
if(temp == true)
{
alert("Checkbox is checked");
}
else
{
alert("Checkbox is NOT checked");
}
}
I am trying to create a javascript function within my html document that essentially takes the value of each <td> and places it in the textbox. Any help is very appreciated.
<html>
<head>
<script type="text/javascript">
function typeThis(){
document.getElementById('box_1').value = document.getElementById('typewriter');
}
</script>
<style type="text/css">
td{
border:1px solid black;
padding:10px 10px 10px 10px;
font-family:"Helvetica Neue";
font-size:20px;
}
table{
margin-top:50px;
}
</style>
</head>
<body>
<table id = "typewriter">
<td value="k" onclick="typeThis();">k</td>
<td value="c" onclick="typeThis();">c</td>
<td value="y" onclick="typeThis();">y</td>
<td value="s" onclick="typeThis();">s</td>
<td value="p" onclick="typeThis();">p</td>
<input type="text" id="box_1">
</table>
</body>
</html>
value is a custom property for a td,
so you can access it using this method
function typeThis(){
document.getElementById('box_1').value = this.getAttribute("value");
}
Side Note:
this is how your table should look like
<table id = "typewriter">
<tr>
<td value="k" onclick="typeThis();">k</td>
<td value="c" onclick="typeThis();">c</td>
<td value="y" onclick="typeThis();">y</td>
<td value="s" onclick="typeThis();">s</td>
<td value="p" onclick="typeThis();">p</td>
</tr>
</table>
<input type="text" id="box_1">
Example 2:
function typeThis(letter){
document.getElementById('box_1').value = letter;
}
<table id = "typewriter">
<tr>
<td value="k" onclick="typeThis('k');">k</td>
<td value="c" onclick="typeThis('c');">c</td>
<td value="y" onclick="typeThis('y');">y</td>
<td value="s" onclick="typeThis('s');">s</td>
<td value="p" onclick="typeThis('p');">p</td>
</tr>
</table>
How about
var box = document.getElementById("box_1");
var tds = document.getElementsByTagName("td");
for (var i = 0; i < tds.length; i++) {
var valToAdd = tds[i].textContent ? tds[i].textContent :
(tds[i].innerText ? tds[i].innerText : tds[i].innerHTML);
box.value = box.value + valToAdd;
}
to avoid using innerHTML it checks for the newer textContent and uses it if present. If not, it falls back to innerText and, as a last resort, innerHTML.
Also, if you want to add custom attributes to your td tags, you may want to opt for the more standard data-value="k" format. And check your code for a closing table tag
The main problem is on this line:
document.getElementById('box_1').value = document.getElementById('typewriter');
You are assigning the value of the 'box_1' input equal to the table element itself, not to the value from the particular td that was clicked.
If you change your function to accept a parameter that is the clicked td you can then access the value property:
function typeThis(el){
document.getElementById('box_1').value = el.getAttribute('value');
}
// then change each TD to look like this:
<td value="k" onclick="typeThis(this);">k</td>
However, you can simplify your code somewhat if you use a single click handler on the table instead of putting one on every individual td. When a td is clicked that event "bubbles up" to the containing tr and then to the table, so you handle it there and check the event object to see which td was the actual target:
function typeThis(e) {
// allow for the way IE handles the event object
// compared to other browsers
e = e || window.event;
var el = e.srcElement || e.target;
if (el.tagName.toLowerCase() === "td")
document.getElementById('box_1').value = el.getAttribute('value');
}
document.getElementById('typewriter').onclick = typeThis;
Regarding your table html, some browsers may guess what you meant and display it OK, but you should have a closing </table> tag and your tds should be in a tr. Note that I've removed all of the onclick assignments because with the code above that assigns one for the table you don't need them:
<table id="typewriter">
<tr>
<td value="k">k</td>
<td value="c">c</td>
<td value="y">y</td>
<td value="s">s</td>
<td value="p">p</td>
</tr>
<table>
Note that at the moment each td's value is exactly the same as its innerHTML, so you could just remove all of the value properties from the markup and user .innerHTML in your function instead of getting the value of value:
document.getElementById('box_1').value = el.innerHTML;