Use Greasemonkey to remove tables - javascript

I am trying remove 2 tables from simple html page. The page contain only 2 tables, Heres the page code:
<html>
<body>
<h3>Table 1</h3>
<table class="details" border="1" cellpadding="0" cellspacing="0">
<tbody><tr>
<th>1</th>
<td>2</td>
</tr>
</tbody></table>
<h3>Table 2</h3>
<table class="details" border="1">
<tbody><tr>
<th>1</th>
<td>2</td>
</tr><tr>
<th>3</th>
<td>4</td>
</tr>
</tbody></table>
</body>
</html>
I have no problem removing one of the tables using:
var elmDeleted = document.getElementsByClassName('details').item(0);
elmDeleted.parentNode.removeChild(elmDeleted);
or
var elmDeleted = document.getElementsByClassName('details').item(1);
elmDeleted.parentNode.removeChild(elmDeleted);
But I fail to remove both tables using those command in a row on my user script:
var elmDeleted = document.getElementsByClassName('details').item(0);
elmDeleted.parentNode.removeChild(elmDeleted);
var elmDeleted = document.getElementsByClassName('details').item(1);
elmDeleted.parentNode.removeChild(elmDeleted);
Please advise

Once you remove the old table #0, the old table #1 becomes the new table #0. Thus, if you try to get table #1, it'll fail.

Sebastian's answer really is the answer you'll be looking for, but for clarity, I'll show how you could do it:
You could either do
var elmDeleted = document.getElementsByClassName('details').item(0);
elmDeleted.parentNode.removeChild(elmDeleted);
var elmDeleted = document.getElementsByClassName('details').item(0);
elmDeleted.parentNode.removeChild(elmDeleted);
Watch the fact that I'm removing the .item[0] both times; it'll remove the first one on the page both times.
Else, this:
var elmDeleted = document.getElementsByClassName('details').item(1);
elmDeleted.parentNode.removeChild(elmDeleted);
var elmDeleted = document.getElementsByClassName('details').item(0);
elmDeleted.parentNode.removeChild(elmDeleted);
... Which will remove the second, then the first one.
To be (what I call) neat: (==more compact)
for(i=0;i<2;i++)(temp=document.getElementsByClassName('details').item(0)).parentNode.removeChild(temp);
As a side note, since you say that there'll be only 2 tables on the page, you can replace every document.getElementsByClassName('details') with document.getElementsByTagName('table').
Also, in my compact version, you can replace the i<2 with i<document.getElementsByClassName('details').length to remove all 'detail'-tables instead of just the first two.
Hope this helped :)

Related

Displaying HTML Element Count

I'm doing Free Code Camp projects with User Stories requiring a minimum number of different elements.
I came up with the idea of using some of the page to display an element count and thought it would be simple to implement. Famous last words I know.
Spent a few hours reviewing MDN , W3, W3Schools, ... examples and documentation. Also searched here.
I've tried using botj javascript and jQuery and can get results in javascript but they are incorrect. The jQuery stuff doesn't work at all.
<head>
<script src=
"https://code.jquery.com/jquery-2.2.4.min.js">
</script>
<script src=
"https://code.jquery.com/jquery-3.5.0.js">
</script>
</head>
<body>
<!-- much deletia -->
<div class="ToC">
<div>
<table>
<tr>
<th colspan="2">HTML Element Use</th>
</tr>
<tr>
<td>Name</td><td>Count</td>
</tr>
<tr>
<td>Total</td><td><script>document.write(HTMLCollection.length)</script></td>
</tr>
<tr>
<td>p</td><td><script>document.write(document.getElementsByTagName('p').length);</script></td>
</tr>
<tr>
<td>div</td><td><script>document.write($( div ).length;)</script></td>
</tr>
</table>
</div>
</div>
<!-- even more deletia -->
</body>
What am I doing wrong?
var divCnt = document.getElementsByTagName('div').length
var pCnt = document.getElementsByTagName('p').length
var tCnt = document.getElementsByTagName('*').length
document.getElementById('total').innerHTML = tCnt;
document.getElementById('div').textContent = divCnt;
document.getElementById('p').innerHTML = pCnt;
<head>
<script src=
"https://code.jquery.com/jquery-2.2.4.min.js">
</script>
<script src=
"https://code.jquery.com/jquery-3.5.0.js">
</script>
</head>
<body>
<!-- much deletia -->
<div class="ToC">
<div>
<table>
<tr>
<th colspan="2">HTML Element Use</th>
</tr>
<tr>
<td>Name</td><td>Count</td>
</tr>
<tr>
<td>Total</td><td id='total'></td>
</tr>
<tr>
<td>p</td><td id='p'></td>
</tr>
<tr>
<td>div</td><td id='div'></td>
</tr>
</table>
</div>
</div>
<!-- even more deletia -->
</body>
This gets all of the elements from a simple document.querySelectorAll('*') which matches everything. Calling that returns a NodeList, so you want to turn that into an array using Array.from(...).
The next line uses the Array reduce method to turn that array of many elements into a single map.
It does that by using the node tagName as the key into the map, and assigning the node to that key. Actually it has to create an array on the map element first, so it can push all of the similar nodes onto that array.
That is done by using the element type name, such as DIV, as the key into the map. If that's the first time a node type has been seen it creates the array and then, in all cases, pushes the Element into the array.
let allelements = Array.from(document.querySelectorAll('*'));
let result = allelements.reduce(function(map, obj) {
if (map[obj.tagName] == null) {
map[obj.tagName] = [];
}
map[obj.tagName].push(obj);
return map;
}, {});
console.log(result);
<div id="div-one">
<p>one</p>
<p>two</p>
</div>
<div id="div-two">
<p>three</p>
<p>four</p>
<p>five</p>
</div>
You can then iterate the map keys to find how many of each element type there is.
If all you care about is the total element count you can skip reducing the array and just use allelements.length which tells you how many total nodes were selected.
Notice this gets ALL elements! You can limit it to just the <body> elements by first selecting the body and then using querySelectorAll on that.
In this example I've also added summarizing the number of each element type to the console.
let body = document.querySelector('body');
let allelements = Array.from(body.querySelectorAll('*'));
let result = allelements.reduce(function(map, obj) {
if (map[obj.tagName] == null) {
map[obj.tagName] = [];
}
map[obj.tagName].push(obj);
return map;
}, {});
console.log('Resulting map =', result);
console.log('Counts:');
for (tag of Object.keys(result)) {
console.log(tag.toLowerCase(), result[tag].length);
}
<div id="div-one">
<p>one</p>
<p>two</p>
</div>
<div id="div-two">
<p>three</p>
<p>four</p>
<p>five</p>
</div>

How can I change table navbar with CSS in an extension?

I am currently developing a Chrome extension for my university and I have done most of the things I want to do but I am having difficulty with one thing is that whenever I try to select the first <table> tag which is the navbar in this link I can't seem to hide it and then add my custom navbar using CSS.
Here is my code (I have included random createtextnode that I want to add to give a sense for what I want do or I am trying to do):
CSS
table:nth-child(1)
{
display:none;
}
JavaScript
var note = document.getElementsByName('stud_login')[0];
var par = document.createElement("div");
var tag = document.createElement("a");
var t1 = document.createTextNode(" Hello! Please try to refresh page again if the verification is not filled properly.");
var t2 = document.createTextNode("Click here");
var t3 = document.createTextNode(" Any suggestions? ");
var br = document.createElement("br");
par.setAttribute("class", "info-msg");
par.appendChild(t1);
tag.setAttribute("href", "http://goo.gl/forms/QI8gPMfKML");
tag.setAttribute("target", "_blank");
tag.setAttribute("id", "rahultag");
par.appendChild(t3);
tag.appendChild(t2);
par.appendChild(tag);
note.parentElement.appendChild(par);
Here is the HTML code i want to target and is the first table that occurs:
<table width="100%" height="15%" border="0" align="center" cellpadding="0" cellspacing="0" background="images/banner_bg3.jpg">
<tr>
<td width="25%" align=left>
<img src="images/vit_logo6.jpg" height="76" width="297">
</td>
<td align=center>
<br>
<font size=5 color=#FFFFFF face="Comic Sans MS">
<b>V-TOP</b><br>Student Login
</font>
</td>
</tr>
</table>
To target the first table, then this would likely give you the desired result
var note = document.getElementsByTagName('table')[0];
If the table is not the first element in its parent, you need to use insertBefore instead of appendChild
note.parentElement.insertBefore(par, note);
Side note:
If the table:nth-child(1) { display: none; } won't work, you could use replaceChild to replace the table with your new element
note.parentElement.replaceChild(par, note);
or simply remove it
note.parentElement.removeChild(note);
Note though, that if you are to remove it, do that after you inserted the new, or else there will be no reference where to insert the new.
If you still need to remove before add, read more here how to get the element to be removed's next sibling: https://developer.mozilla.org/en-US/docs/Web/API/Node/insertBefore

How to print a HTML Data which is in a String

I have a Print button in my Project. I am using JavaScript to print the data. I have a variable as data_to_print which contains the HTML which is to be print. The problem is that when i hit the print button the print dialog window of windows does not open. I am not able to find whats the problem, can any one help me.
Below is my Code:
function print_all()
{
var xx='<html>
<head>
<style>...</style>
</head>
<body>
<center>
<div>
<table><thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Address</th>
<th>DOB</th>
</tr><thead>
<tr>
<td>1</td>
<td>John</td>
<td>Mumbai</td>
<td>15 August</td>
</tr>
<tr>
<td>2</td>
<td>John2</td>
<td>Mumbai2</td>
<td>18 August</td>
</tr>
</table>
</div>
</center>
</body>
<html>';
var content_vlue = xx;
content_vlue=content_vlue.replace("[Print]", "");
var docprint=window.open("","","");
docprint.document.open();
docprint.document.write('<html><head>');
docprint.document.write('<style> .table{border-collapse:collapse;}.table tr
th{border:1px solid #000!important;color:#000;}.table tr th
a{color:#000!important;}.table tr td{border:1px solid #000!important;}</style>');
docprint.document.write('</head><body><center>');
docprint.document.write('<div align="left">');
docprint.document.write(content_vlue);
docprint.document.write('</div>');
docprint.document.write('</center></body></html>');
docprint.document.close();
docprint.focus();
}
The reason for your trouble is quit simple. You forgot to add the method .print();.
When I understand your right, then do following:
function print_all()
{
...
docprint.document.close();
docprint.focus();
//This line was missing
doc.print();
}
Addationaly two advices:
First:
As steo wrote, if you want to print long string in Javascript, concatinate it with the plus sign. The browsers don't accept line breaks within strings.
Second:
When I used your definition for the link <a title="Print" onClick="print_all();" class="no-bord btnlite" target="_blank">print</a> it did open the opener page also in a new tab. Another effect ourccur when I opend the site in IE. The effect: he didn't marked this line as clickable link.
To solve these, use this line <a title="Print" href="#" onClick="print_all();return false;" class="no-bord btnlite" target="_blank">print</a> .

Change class by evaluating innerHTML

I'm trying to change the style of a <span> by changing its class. I'm evaluating its text value and want it to change the className to 'red' if it's less than 97.7, or to 'green' if it's anything else. I'm evaluating all <span> of class "qadata".
function changeColor() {
var cells = document.getElementsByTagName('span').getElementsByClassName('qadata');
for (var i=0, len=cells.length; i<len; i++) {
if (parseFloat(cells[i].innerHTML) < 97.7){
cells[i].className = 'red';
}
else {
cells[i].className = 'green';
}
}
}
I'm trying to do this in the following HTML table:
<table datasrc='#QA' class="qa">
<thead>
<tr>
<th>Period</th>
<th>Safety</th>
<th>Quality</th>
<th>Shipping</th>
</tr>
</thead>
<tbody>
<tr>
<td class="leftcolumn"><span datafld='Period' width=100%></span></td>
<td><span datafld='Safety' width=100% class="safety"></span></td>
<td><span datafld='Quality' width=100% class="qadata"></span></td>
<td><span datafld='Shipping' width=100% class="qadata"></span></td>
</tr>
</tbody>
</table>
The data is populated using another function prior to calling changeColor(). This is a corporate intranet site, so I'm currently stuck using ie8 or ie10. JavaScript is preferable to jQuery in this instance.
I've been doing HTML and CSS for years, but never got into JavaScript until recently. I tried searching but haven't found a method posted here that works.
I created a jsfiddle that seems to work. I just used the:
document.querySelectorAll('span.qadata')
It changes the class names for the spans with class qadata. http://jsfiddle.net/mYUjL/

Adding row in a table with javascript = strange result in Chrome and safari

I've got to add a new row with it's content populated from an ajax query when I click on any row present. Everything is working well in ie8, ff3.6, opera11, but in chrome10 and safari5 the row are always shown as the first row even if the HTML code is well ordered.
the javascript use is here:
jQuery('.tx_tacticinfocours_pi1_cour_line').click(function (){
if(running==false){
running=true;
jQuery('.cour_detail_temp_inner').slideUp(500, function () {
jQuery(this).parents('.cour_detail_temp').remove();
});
var td=jQuery(this).after('<tr class="cour_detail_temp"><td colspan="8" style="padding: 0pt;"><div class="cour_detail_temp_inner" style="display: none;"></div></td></tr>');
td=td.next().find('.cour_detail_temp_inner');
var url=jQuery(this).find('.tx_tacticinfocours_pi1_detail_link a').attr('href');
td.load(url,function(){
jQuery(this).slideDown(500,function(){running=false;});
});
}
});
and here is the HTML (it's typo3 template):
<table class="tx_tacticinfocours_pi1_liste" border="0" cellspacing="0" cellpadding="0">
<tr>
<th>###TITRE_WEB###</th>
<th>###TITRE_PDF###</th>
<th>###TITRE_DETAILS###</th>
<th>###TITRE_SIGLE###</th>
<th>###TITRE_TITRE###</th>
<th>###TITRE_ENLIGNE###</th>
<th>###TITRE_ENSEIGNANT###</th>
<th>###TITRE_RESPONSABLE###</th>
</tr>
<!-- ###COURS### begin -->
<tr class="tx_tacticinfocours_pi1_cour_line">
<td class="tx_tacticinfocours_pi1_link"><!-- ###COURS_LINK### begin -->###COURS_WEB_IMAGE###<!-- ###COURS_LINK### end --></td>
<td class="tx_tacticinfocours_pi1_link"><!-- ###PDF_LINK### begin -->###PDF_IMAGE###<!-- ###PDF_LINK### end --></td>
<td class="tx_tacticinfocours_pi1_link tx_tacticinfocours_pi1_detail_link"><!-- ###DETAILS_LINK### begin -->###DETAILS_IMAGE###<!-- ###DETAILS_LINK### end --></td>
<td class="tx_tacticinfocours_pi1_sigle" nowrap>###COURS_SIGLE###</td>
<td class="tx_tacticinfocours_pi1_titre">###COURS_TITRE###</td>
<td class="tx_tacticinfocours_pi1_enligne">###COURS_ENLIGNE###</td>
<td class="tx_tacticinfocours_pi1_enseignant" nowrap>###COURS_ENSEIGNANT###</td>
<td class="tx_tacticinfocours_pi1_responsable" nowrap>###COURS_RESPONSABLE###</td>
</tr>
<!-- ###COURS### end -->
have you got any idea why it's doing so or any work around?
I'm not sure, but try turning:
var td=jQuery(this).after(...)
to: var td=jQuery('<tr class="cour_detail_temp"><td colspan="8" style="padding: 0pt;"><div class="cour_detail_temp_inner" style="display: none;"></div></td></tr>').appendTo(this);
I think what you've got there is more of a css problem than a javascript problem.
I stumbled upon this today. Turns out the "main rows" in my table had display:block, which makes the new ones that have display:table-row end up on top even if they're mingled in the HTML. Having display:table-row on the "main rows" leaves the inserted ones in place. Go figure! (Safari only)
Not sure this is the problem, but instead of:
var td=jQuery(this).after(...)
try this:
var td=jQuery(this).parent().after(...)

Categories

Resources