I have this piece of code:
for (var i = 0, row; row = document.getElementById("myTbl").rows[i]; i++) {
row.cells[headCatg.cellIndex].classList.remove("red");
row.deleteCell(headCatg.cellIndex);
}
I need to remove the class "red" from each cell of the table column and then delete that column. The reason I need to remove class first, because it has been added to DOM by another cript and if I remove the column the class just appears in the next column.
When I run each of these commands (remove() and deleteCell()) individually in the loop, everything seem to work fine, but when I put them together, the column is removed but the class shifts to another column.
What am I missing?
You have to convert the HTMLcollection to an array
The reason why your code wasn't working properly it's because HTMLcollection returns a live NodeList which means when you use remove on each element in the collection the other elements gets rearranged and the length of the list get's smaller causing you to skip some of them so you should convert your html collection to an array using Array.from
row = document.getElementByClassName("myTbl")
rowarr=Array.from(row)
for (var i = 0, rowarr.length; i++) {
row[i].cells[headCatg.cellIndex].classList.remove("red");
row[i].deleteCell(headCatg.cellIndex);
}
Related
I'm very new to Javascript and jQuery. I'm trying to create a film list that will randomly pick an item from the list, post the result, and remove the item from the original list. It uses text input, .push and .append to keep track of the list and update an array of matching text. My thinking was that I would use an array that matches the ul to generate a random index number from its length and then use the number to remove the li from the ul by index. The basic idea is working. My issue is that every time it selects an item from the list, the item it removes from the array is different than the item it posts and removes from the ul. The parts seem to work fine separately until I run them in a function together tied to a button.
Here is the code I'm using. The watchList array is populated with a .push whenever text is accepted to update the ul. I've checked and the index for both match up.
function randomShow(){
var r = Math.floor(Math.random() * watchList.length);
for(var i = 0; i < watchList.length; i++){
if(i === r) {
alert(watchList[i]);
watchList.splice(watchList.indexOf[i],1);
$("li").eq(i).remove();
}
}
}
I think you don’t need a loop. Try this;
function randomShow(){
var r = Math.floor(Math.random() *watchList.length);
$("li").eq(r).remove();
}
I have this fiddle that sorts items on my webpage. I can see it works by checking the console.log results. I just don't know how to make the results appear on the actual webpage -- the items sorted in order.
http://jsfiddle.net/AQFFq/21/
function myFunction() {
var elements = [].slice.call(document.getElementsByClassName("price"));
elements.sort(function(a, b) {
return parseFloat(b.innerHTML.substring(1)) - parseFloat(a.innerHTML.substring(1));
});
for (var i = 0; i < elements.length; i++)
elements[i].parentNode.appendChild(elements[i]);
console.log(elements);
}
Thanks.
as i mentioned in my comments you have a couple of problems with your sorting. 1 there isnt {} around your for loop so it is only running once. 2 your are appending the price to its own parent node and since the parent nodes are still in their original order the function does nothing. what you need to do is select the parent node that is the entire element you want to sort and append that to the first parent node your sortable items have in common. here is a jsfiddle for what i mean functioning fiddle ps i switched a and b in your sort function so that the result is actually different then the original page.
I have this array that is auto generated based on images in a gallery. I need to give them all seperate click events that output variables from another array on click so I can pass them into a string that is attached to the end of a url to submit to pinterest. The part that is slipping me up is the click event,
Here is the code, so far it just alerts last part of the array and does it twice, I want each click to alert seperately the first array for the first click, and the second array position for the second clicked.
THis is the corresponding array console.logged, it is the individual classes for different buttons to click.
[".btnPinIt , 0", ".btnPinIt , 1"]
for (var j = 1; j < clickArray.length; j++){
console.log(clickArray[j]);
$(clickArray[j]).click(function() {
alert(j);
});
}
One problem is your j is in the same scope for all handlers, so has a value of clickArray.length when the click occurs, but you should not need separate handlers for this. Use data attributes on the elements and pick them up from a single handler.
Another is that you are indexing the array from 1 instead of 0.
You also need an array that has valid selectors as, at the moment, you have an array of invalid jQuery selectors.
e.g. Assuming you have an array of id selectors:
clickArray = ["#btnPinIt1",
"#btnPinIt2"]
// save the index values on the elements
for (var j = 0; j < clickArray.length; j++){
$(clickArray[j]).attr('data-val', j+1);
}
// Use a startswith selector (in this example) to handle the clicks
$("[id^=btnPinIt]").click(function() {
alert($(this).data('val'));
});
Simpler still would be to use your class and index them in order from 1 to n:
$('.btnPinIt').each(function(e, i){
$(this).attr('data-val', i+1);
}).click(function() {
alert($(this).data('val'));
});
This also chains the click and each.
I have the following piece of code that finds all elements in the document with classname foo and then removes them all
function(doc) {
var items = doc.getElementsByClassName('foo');
alert(items.length);
if(items.length>0) {
for(var i=0;i<items.length;i++) {
alert(i);
doc.body.removeChild(items[i]);
}
}
Forexample, the items.length is 3 and the function exits after running one loop and when the length is 8 it exits at 3. Any help would be greatly appreciated. Also, when I run the function again and again it does eventually remove all elements.
Your problem is that the NodeList returned by getElementsByClassName() is live. Either convert it into an array first as Felix suggests or iterate backwards:
var items = doc.getElementsByClassName('foo');
var i = items.length;
while (i--) {
items[i].parentNode.removeChild(items[i]);
}
This works because the item removed from the list each iteration is the last item in the list, therefore not affecting earlier items.
I also changed doc.body to items[i].parentNode for greater generality, in case you need to deal with elements that are not direct children of the <body> element.
The problem is that items is a live NodeList, i.e. whenever you access a property of the list (items.length), the list is reevaluated (elements are searched again).
Since you delete elements in the meantime, the list becomes shorter, but you keep the index.
You could convert the NodeList to an array first:
var items = [].slice.call(doc.getElementsByClassName('foo'));
The array size won't change when you delete the DOM elements.
I was trying to delete elements with a particular class name, but it doesnt work. Any idea why?
function delete_elems(){
var my_elems = document.getElementsByClassName("my_elem");
for(k=0; k<my_elems.length; k++){
my_elems[k].parentElement.removeChild(my_elems[k]);
}
}
I also tried:
function delete_elems(parentElem){
var my_elems = document.getElementsByClassName("my_elem");
for(k=0; k<my_elems.length; k++){
parentElem.removeChild(my_elems[k]);
}
}
Begin at the end:
for(k=my_elems.length-1;k>=0; --k)
http://jsfiddle.net/doktormolle/fDNqq/
The getElementsByClassName method returns a live node list, so iterating over it using an index and at the same time modifying the list (by removing nodes from the document) means that as elements are removed, the list is modified so what started as a list with 10 members will only have 9 once one is removed. If you remove item 0, then all items are re-indexed so what was item 1 is now 0, 2 is 1 and so on up to 8 (since there are only 9 left).
As noted by Dr. Molle, you may be able to avoid this issue by iterating over the list from the end.
You can avoid a counter altogether:
var el;
while ((el = my_elems[0])) {
el.parentNode.removeChild(el);
}
Note that when using a NodeList, each time an element is removed, the list must be re-generated by the browser (regardless of which of the above methods is used) so this method will likely be slow where the nodeList is large.
You can avoid that by converting the list to an array first (simply iterate over it) in which case you can use either an incrementing or decrementing counter and not worry about missing members in the list (since it isn't modified when elements are removed from the document).