Remove NodeList from another NodeList - javascript

How can I remove one NodeList from another? For example, if I have:
var all = document.querySelectorAll('*');
var divs = document.querySelectorAll('div');
var removed = all - divs;
This doesn't work however. What is the correct method for doing this with the result being a nodelist and not an array?

You can turn the all nodeList into an array and then use array methods to do searching and removals:
var all = Array.prototype.slice.call(document.querySelectorAll('*'), 0);
var divs = document.querySelectorAll('div');
for (var i = 0; i < divs.length; i++) {
var pos = all.indexOf(divs[i]);
if (pos !== -1) {
all.splice(pos, 1);
}
}
This requires IE9 (for .indexOf()) or you can use a polyfill to make it work in older versions of IE or you can make your own function that iterates through an array to find if an element matches.
On second thought, there's a bit of an easier way to do this:
var all = Array.prototype.slice.call(document.querySelectorAll('*'), 0);
for (var i = all.length - 1; i >= 0; i--) {
if (all[i].tagName === "DIV") {
all.splice(i, 1);
}
}

var all = document.querySelectorAll('*');
var divs = document.querySelectorAll('div');
var removed = all.filter(function(i){
return divs.indexOf(i) < 0;
});

Related

How to remove all elements except last one with same document.querySelectorAll(".someClass") using only javascript without jQuery

My query is simple :
How to remove all elements except last one with same document.querySelectorAll(".someClass") using only javascript without jQuery.
I can do it with jQuery with only one line like this:
$('.someClass').not(':last(2)').remove();
But I want to do it with pure JavaScript; how can I do that?
Any idea?
I tried this code :
var lists = document.querySelectorAll(".someClass");
for(var i = 1; i < lists.length; i++) {
lists[i].parentElement.removeChild(lists[i]);
}
But it removes all elements except the first one. But I want to keep the last one.
This will remove all but the last element from your nodeList
EDIT:
const elems = Array.from(document.querySelectorAll(".someClass"))
elems.pop()
elems.map(node => node.parentNode.removeChild(node))
var lists = document.querySelectorAll(".someClass");
for(var i = 0; i < lists.length -1; i++) {
lists[i].parentElement.removeChild(lists[i]);
}
Try using this.
var lists = document.querySelectorAll(".someClass");
for(var i = 1; i < lists.length; i++) {
if (i !== lists.length - 1) lists[i].parentElement.removeChild(lists[i]);
}
You can perform the above action on every item in the array except for the last one (the last index is array.length - 1 since the first index is 0.
You were close:
let endIndex = 1 // how many you want to delete
var lists = document.querySelectorAll(".someClass");
for(var i = 0; i < lists.length - 1 - endIndex; i++) {
lists[i].parentElement.removeChild(lists[i]);
}
Stop just before the last one:
var lists = document.querySelectorAll(".someClass");
for(var i = 1; i < lists.length - 1; i++) {
// ^^^^−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
lists[i].parentElement.removeChild(lists[i]);
}
Or alternatively, in all vaguely-modern browsers:
const lists = Array.prototype.slice.call(
document.querySelectorAll(".someClass"),
0, -1
);
for (const list of lists) {
list.remove();
}
That uses the slice method from Array.prototype to grab all of the entries from the NodeList returned by querySelectorAll except the last one, then loops over that result removing those elements.
Try with this:
$("#parent_id").children(":not(#id_n)").remove();

In Javascript how do I iterate the results of getElementsByClassName() and modify display attribute

How do I iterate the results of getElementsByClassName()
This is what I had:
function togglePotentialMatchesLinks()
{
alert("fred");
var els = document.getElementsByClassName("releasegroupingpotential");
var e;
for(e in els)
{
e.style.display = e.style.display=="none"
?"table-row-group"
:"none";
}
return true;
}
I have since read its not actually an array but a NodeList or a HtmlCollection, but that has left me none the wiser how to modify the function so that it works.
Update
Now working based on Trandences answer
function togglePotentialMatchesLinks()
{
var els = document.getElementsByClassName("releasegroupingpotential");
var e;
for (var i = 0; i < els.length; ++i) {
e = els[i];
e.style.display = e.style.display=="none"
?"table-row-group"
:"none";
}
return true;
}
Per the docs: https://developer.mozilla.org/en-US/docs/Web/API/NodeList
for (var i = 0; i < myNodeList.length; ++i) {
var item = myNodeList[i]; // Calling myNodeList.item(i) isn't necessary in JavaScript
}
Yes, it's a NodeList but that's OK. You can check for a number of properties to accomplish your goal, such as collection.item && collection.length. Here is a way to do it: http://jsbin.com/bajomi/1/edit?js,output

Two different types of NodeLists? Cannot set properties on one NodeList to Array

These two examples are both node lists, but only the first works.
Works as expected:
var apple = document.getElementById('apple');
var nodeList = document.getElementsByTagName('li'); // Line of concern
var array = [];
for(var i = 0; i < nodeList.length; i++) {
array[i] = nodeList[i];
}
for(var i = 0; i < array.length; i++) {
array[i].style.display = 'none';
}
Does not work (error is: "Uncaught TypeError: Cannot set property 'display' of undefined"):
var apple = document.getElementById('apple');
var nodeList = apple.parentNode.childNodes; // Line of concern
var array = [];
for(var i = 0; i < nodeList.length; i++) {
array[i] = nodeList[i];
}
for(var i = 0; i < array.length; i++) {
array[i].style.display = 'none';
}
So if both variables "nodeList" are actual node lists, then why can't I set the properties on the latter example, nor anything similar.
Also, how do I solve the issue on the latter?
No jQuery please for this question.
Thank you.
There are not two different types of NodeLists.
apple.parentNode.childNodes
returns a NodeList, but it contains ALL the nodes--including new line & space characters between elements on the HTML. So the reason I couldn't apply the properties I wanted was because some of the nodes were non-elements.
The answer then in place of that, is to use the element-only selecting methods; in this case: parentElement & children:
apple.parentElement.children
See Mozilla's Developer page on nodes, as well as the left-hand column for more node methods.

Remove elements whose id name contains certain string

I want to remove all elements (suppose they're all divs) whose id name contains the string bs. How to do this via javascript regardless of they are nested elements or not? (not jquery)
<div id="new_bs_add"></div>
<div id="bsremove"></div>
<div id="somethingelse"></div>
... and many more
No jQuery, but if there's support for CSS3 selectors you can go for
var rem = document.querySelectorAll("[id*='bs']"), i = 0;
for (; i < rem.length; i++)
rem[i].parentNode.removeChild(rem[i]);
Otherwise, just go for this slight edit of VisioN's solution:
var divs = document.querySelectorAll("[id]");
for (var i = 0, len = divs.length; i < len; i++) {
var div = divs[i];
if (div.id.indexOf("bs") > -1) {
div.parentNode.removeChild(div);
}
}
Pure JavaScript:
var divs = document.getElementsByTagName("div");
for (var i = divs.length; i;) {
var div = divs[--i];
if (div.id.indexOf("bs") > -1) {
div.parentNode.removeChild(div);
}
}
As an example, in jQuery it is one line:
$("div[id*='bs']").remove();
DEMO: http://jsfiddle.net/c4ewU/
The most portable method to obtain a list of elements is document.getElementsByTagName. However the resulting list is a live node list which means that if you modify the document, the list changes too!
There are two solutions for this. One is to take a copy of the list:
var nodes = document.getElementsByTagName('div');
var copy = [].slice.call(nodes, 0); // take a copy
for (var i = 0, n = copy.length; i < n; ++i) {
var d = copy[i];
if (d.parentNode && d.id.indexOf('bs') >= 0) {
d.parentNode.removeChild(d);
}
}
The second is to either work through the list backwards, or ensure that you don't advance the iterator if you modify the list. This takes the latter approach:
var nodes = document.getElementsByTagName('div');
for (var i = 0; i < nodes.length; /* blank */ ) {
var d = nodes[i];
if (d.id.indexOf('bs') >= 0) {
d.parentNode.removeChild(d);
} else {
++i; // iterate forward
}
}
try this code
first get all elements contain certain text (here 'bs')
var matches = [];
var searchElements = document.getElementsByTagName("body")[0].children;
for(var i = 0; i < searchElements.length; i++) {
if(searchElements[i].tagName == 'DIV') {
if(searchElements[i].id.indexOf('bs') != -1) {
matches.push(searchElements[i]);
}
}
}
Then delete them from body of html
for(var i = 0;i<matches.length; i++)
matches[i].parentNode.removeChild(matches[i]);
If you remove them in the first loop, there will be some tags will not deleted as the children array length is decreased each time you delete a node. So the better way to get them all in an external array and then delete them.

getElementsByTagName Exclude Elements (Filter)

I have a JavaScript selector like this:
var inputs = document.getElementsByTagName("input");
This works great except that I want to filter out some inputs (the ones with the class of "exists")
How can I do this without jQuery?
This is what you need:
var inputs = document.getElementsByTagName("input");
var neededElements = [];
for (var i = 0, length = inputs.length; i < length; i++) {
if (inputs[i].className.indexOf('exists') >= 0) {
neededElements.push(inputs[i]);
}
}
Or, in short (as provided by knee-cola below):
let neededElements = [].filter.call(document.getElementsByTagName('input'), el => el.className.indexOf('exists') >= 0);

Categories

Resources