getElementByTagName not working? - javascript

In the code below, I am applying a different background color to all even rows by dynamically assigning the class "even" to them using javascript. I am calling the alternamte() function onload of the body tag.
At first, I was using getElementById to get the table object and my code worked fine. However, I am suppose to apply this styling to ALL tables on my page, so I need to use get element by tag name.
Once I made the chane to getElementByTagName, my code stopped working and I have been trying to find out the root of the problem for a while now with no success. I was wondering if someone can help me understand why my code stopped working after I made the change to getElementByTagName?
<script type="text/javascript">
function alternate(){
var table = document.getElementsByTagName("table");
var rows = table.getElementsByTagName("tr");
for(i = 0; i < rows.length; i++){
//change style of even rows
//(odd integer values, since we're counting from zero)
if(i % 2 == 0){
rows[i].className = "even";
}
}
}
</script>

It's getElementsByTagName(), plural. It returns a HTMLCollection
var table = document.getElementsByTagName("table")[0];
(if you're confident that there's a <table> on the page.)
If you want to do things to all the <table> elements, you'd have to do something like this:
var tables = document.getElementsByTagName("table");
for (var ti = 0; ti < tables.length; ++ti) {
var rows = tables[ti].getElementsByTagName("tr");
for(var i = 0; i < rows.length; i++){
//change style of even rows
//(odd integer values, since we're counting from zero)
if(i % 2 == 0){
rows[i].className = "even";
}
}
}

Use getElementsByTagName instead of getElementByTagName (getElementsByTagName return multiple node elements )
var table = document.getElementsByTagName("table")[0], trs, rl;
vat tl= table.length;
while(tl--){
trs = tables[tl].getElementsByTagName("tr");
rl = trs.length;
while(rl--){
if(rl % 2 == 0){
trs[rl].className = "even";
}
}
}

getElementsByTagName() returns an array matching the selector. Hence try
var table = getElementsByTagName('table')[indexnumber];

Related

Getting previous element in for loop

EDIT 2 (to make the problem more understandable)
The effect I am trying to achieve is the following: everytime an element enters the viewport an 'is-visible' class is added to it and the same 'is-visible' class is removed from the previous element.
Now I've managed to make it work but I run a for loop to remove all is-visible classes before adding the is-visible class to the element in viewport.
It works but in terms of performance I think it would be better to just remove the class from element[i -1]. And this were I can't get it working.
Here is a simplified fiddle were I try to make the element[i-1] solution work: https://jsfiddle.net/epigeyre/vm36fpuo/11/.
EDIT 1 (to answer some of the questions asked)
I have corrected an issue raised by #Catalin Iancu (thanks a lot for your precious help) by using a modulus operator ((i+len-1)%len).
ORIGINAL QUESTION (not really clear)
I am trying to get the previous element in a for loop (to change its class) with following code :
for (var i = 0; i < array.length; i++) {
if(array[i-1] && my other conditions) {
array[i-1].classList.remove('is-visible');
array[i].classList.add('is-visible');
}
}
But it's not removing the class for [i-1] element.
Here is a more complete piece of code of my module (this is running within a scroll eventlistener):
var services = document.getElementsByClassName('services'),
contRect = servicesContainer.getBoundingClientRect();
for (var i = 0; i < services.length; i++) {
var serviceRect = services[i].getBoundingClientRect();
if ( !services[i].classList.contains('active') && Math.round(serviceRect.left) < contRect.right && services[i-1]) {
services[i-1].classList.remove('is-visible');
services[i].classList.add('is-visible');
}
}
Thanks for your help!
Your if(array[i-1] && my other conditions) is always true, except for the very first case where array[-1] doesn't exist. Therefore, it will remove and then add the active class for each element, which will make it seem as only the first element's class has been removed.
What you need is a better if condition or a break statement, when the loop is not needed anymore
for (var i = 0; i < array.length; i++) {
if(array[i] && i != array.length - 1) {
array[i].classList.remove('active');
}
}
array[array.length - 1].classList.add('active');
The problem probably is that based on your code: services[i-1].classList.remove('active'); and services[i].classList.add('active'); the 'active' class you add in current iteration will be removed in next iteration!
So your code has logical errors, array index does not return all prev items!
What if you create a variable that contain the previous element?
var previous = array[0];
for (var i = 0; i < array.length; i++) {
if(previous && my other conditions) {
previous.classList.remove('active');
array[i].classList.add('active');
break;
}
previous = array[i];
}

Delete object by attribute in javascript

I have a few different tables on the same page but unfortunately they were not assigned any unique id's. I want to remove a table using a JS command, but since id cannot be used, is it possible to delete a table based on a certain attribute it has? For example, is there a command to delete all tables on the page that have the attribute: width="25%" ?
You can use querySelectorAll to do that.
var x = document.querySelectorAll("table[width='25%']");
for (var i=0; i<x.length; i++) { //returns array of elements that match the attribute selector
x[i].remove(); //call prototype method defined below
}
Removing is tricky, I found this code that makes a nice remove method
Element.prototype.remove = function() {
this.parentElement.removeChild(this);
}
NodeList.prototype.remove = HTMLCollection.prototype.remove = function() {
for(var i = 0, len = this.length; i < len; i++) {
if(this[i] && this[i].parentElement) {
this[i].parentElement.removeChild(this[i]);
}
}
}
This creates a prototype remove() function that iterates the node and deletes the children.
Please note that querySelectorAll will not work in IE8 or below, but the poster of the prototype method said that it should work in IE8 but not 7.
I know this already has some solutions, but I'll offer up one more alternative.
var tables = document.getElementsByTagName('table');
for(var i = 0; i < tables.length; i++){
if(tables[i].getAttribute('width') == "25%"){
tables[i].parentNode.removeChild(tables[i]);
}
}
Demo at http://codepen.io/michaelehead/pen/HfdKx.
Yes you can. The easiest way is to use JQuery.
In your javascript code you would just write:
$("[attribute=value]").remove()
So in your case it could be something like $("table[width='25%']").remove()

Javascript getElemtsByClass select [all]

I want to select all elements with the css class
.arrow-down
Sorry but i simply dont find the correct answer, for my problem!
I have an javascript code:
document.getElementsByClassName("arrow-down")[0].style.borderTopColor=""+blu+"";
so how do i select not the first but [all] or is there a way to [1;2;3;]??
getElementsByClassName("arrow-down")[all]
getElementsByClassName("arrow-down")[1;2...]
I tried many things but simply dont get it!
Greetings from germany!
You need to iterate over the list of returned results.
var elements = document.getElementsByClassName("arrow-down");
for (var i = 0, len = elements.length; i < len; i++){
elements[i].style.borderTopColor = blu;
}
If you want to only do a specific subset based on the index, then you can add a condition that checks the value of i. I'm also assuming that blu here is a variable you have defined somewhere?
for (var i = 0, len = elements.length; i < len; i++){
if (i === 1 || i === 2 || i === 3){
elements[i].style.borderTopColor = blu;
}
}
Unfortunately, JavaScript does not have a shorthand for accessing a specific subset of array values, or for applying changes to multiple elements at once. That is something that jQuery does automatically for you. For instance, with jQuery you could write this as:
$('.arrow-down').css('borderTopColor', blu);
document.getElementsByClassName("arrow-down") does select all of such elements.
These are returned in a node list (which can be treated as an array), which is why using [0] on that returns the first element.
Loop over the different elements that the expression returns and act on them:
var elements = document.getElementsByClassName("arrow-down");
var elementsNum = elements.length)
for(var i = 0; i < elementsNum; i++)
{
var anElement = elements[i];
// do something with anElement
}

Javascript get more than one id at a time

I'm just wondering if its possible in javascript to get more than one id at a time, without the use of JQuery. I'm checking the background color of each cell in a dynamically created table. For instance, I have this code:
var black = "rgb(0, 0, 0)";
if(document.getElementById("cell1").style.backgroundColor == black &&
document.getElementById("cell2").style.backgroundColor == black)
{
alert("Two cells are black!");
}
Would it be possible to do something like this:
var black = "rgb(0, 0, 0)";
if(document.getElementById("cell1","cell2").style.backgroundColor == black)
{
alert("Two cells are black!");
}
I'm trying not to use JQuery at all as I'm not too familiar with it.
With modern browsers you can do something similar using querySelectorAll (compatibility matrix), but you'd still have to loop over the resulting NodeList:
var nodes = document.querySelectorAll("#cell1, #cell2");
var count = 0;
for (var index = 0; index < nodes.length; ++index) {
if (nodes[index].style.backgroundColor == black) {
++count;
}
}
if (nodes.length === count) {
alert("Both are black");
}
Doesn't really buy you anything over, say:
var cells = ["cell1", "cell2"];
var count = 0;
for (var index = 0; index < cells.length; ++index) {
if (document.getElementById(cells[index]).style.backgroundColor == black) {
++count;
}
}
if (cells.length === count) {
alert("All cells are black");
}
So in short: No, there isn't really anything more useful you can do.
Not natively. You could write your own fairly easily, though:
function getElementsById(elements)
{
var to_return = [ ];
for(var i = 0; i < elements.length; i++)
{
to_return.push(document.getElementById(elements[i]));
}
return to_return;
}
This will accept an array of IDs as the parameter, and return the elements in an array. You might also want to look into the document.querySelector method.
No,
without using jQuery or other javascript helper libraries.
querySelector is not supported by IE7 and below which still represents a fairly large proportion of the traffice http://caniuse.com/#feat=queryselector
I have upvoted #BenM's answer, but I'd like to suggest another option.
Your issue:
I'm checking the background color of each cell
In this case, it would make more sense to attach the id to the table itself. Your selector becomes (assuming no nested table):
var cells = document.getElementById("myTable").getElementsByTagName("td");
or for recent browsers:
var cells = querySelectorAll("#myTable>tbody>tr>td");
For the record, here is another way if all your cells have a similar id "cellxxx":
var cells = querySelectorAll("td[id^='cell']");

WIndow.onload() not working on IE to hide table rows

window.onload = function(e){
cells = document.getElementsByName('assetID');
for(j = 0; j < cells.length; j++) cells[j].style.display = 'none';
cellsBMPartNo = document.getElementsByName('BMPartNo');
for(j = 0; j < cellsBMPartNo.length; j++) cellsBMPartNo[j].style.display = 'none';
defaultAssetTableValues();
}
I am simply hiding table rows by name.
See line 2 and 4 .
It works fine in Firefox but does not in IE.
Am I missing something ?
IE does not see elements added to the document dynamically (through the DOM) with getElementsByName. Are your elements created that way?
There are other problems with that method in different versions of IE. As a workaround, you could use getElementsByTagName('td') and then check to see if the name attribute matches the one you are looking for in a for-loop, iterating through the array of elements.
Here's a "IE-fixed" version of getElementsByName:
function getElementsByName2(tag, name) {
var els = document.getElementsByTagName(tag);
var arr = [];
for (var i = 0; i < els.length; i++) {
if (els[i].getAttribute("name") == name) {
arr.push(els[i]);
}
}
return arr;
}
And you would use it like so (for elements in table cells with name 'assetID'):
var cells = getElementsByName2('td', 'assetID');
I think the problem may be that <tr> and <td> elements really don't support a "name" attribute. IE doesn't complain directly, but its "getElementsByName()" function will not pay attention to elements like that.
You might want to use a "class" value instead.
IE could be looking for a name with assetID is you assetID defined in the name attribute?
as the others pointed out the name attribute is't for TD`s
ive noticed you have undeclared variables, cells, j, j, cellsBMPartNo also for one of the j's set one of those to i for example to make it easer to follow as well

Categories