I'm using DOMParser() to parse a HTML string, and am trying to get all the child nodes with a for loop. However I do not know how to get the child nodes' nodes, and their children, etc...
var str = "<div><p>paragraph<span>span</span></p></div>";
var doc = new DOMParser().parseFromString(str, 'text/html');
var childnodes = doc.body.childNodes;
for (var i = 0; i < childnodes.length; i++) {
console.log(childnodes[i]);
console.log(childnodes[i].childNodes);
console.log(childnodes[i].childNodes[i].childNodes);
}
This works as I'd like, it gives the div, p, text, and span, but how would I make this work with a for loop that gets all the grandchildren? Without jQuery?
Here's a fiddle with the above code.
You should use recursion for this:
function travelChildren(childnodes){
for (var i = 0; i < childnodes.length; i++) { // for each node in childnodes
console.log(childnodes[i]); // console log current node
travelChildren(childnodes[i].childNodes) // and travel its children
}
}
travelChildren(childnodes) // start recursion with the child nodes you want
For those who can use jQuery, you could do it in a while loop.
var $children = $(document.body).children();
while ($children.length) {
console.log($children.attr('class'));
$children = $children.children();
}
Or as #adeneo suggested, you can use contents():
$(document.body).find('*').contents();
Although, jQuery recommends to "Avoid the All Selector," either way it's likely going to be expensive code.
Related
I am trying to loop through and increment the following:
var result_types = document.querySelectorAll('[data-title]')[0].attributes[2].nodeValue
specifically to grab and increment this value:
[0].attributes
Currently, I have the following:
var card = document.querySelectorAll('[data-title]')[0].attributes[2].nodeValue;
for (var i = 0; i < card.length; i++) {
console.log(card[i]);
}
I am trying to get this [0].attributes to increment to [1].attributes etc. when it is clicked
I am not sure what you are asking here, but if the issue is looping through the elements, this is happening because you get a NodeList back from querySelectorAll and not an array. Below will let you loop through node elements.
const nodes = document.querySelectorAll('.nodes');
[].forEach.call(nodes, (singleNode) => {
//Whatever you want.
})
This might be a little too simple for me to diagnose, but I'm wondering why am I not able to add 'img' to the 'div'.
console does pass the images but it's not appending. I want to remove the elements after.
Thanks in advance
var theLeft = document.createElement('div');
var theLeftElements = theLeftSide.getElementsByTagName('img');
theLeftSide.appendChild(theLeft);
theLeft.appendChild(theLeftElements);
getElementsByTagName returns a NodeList (Similar to an array), whereas appendChild expects its argument to be a Node.
You will need to iterate over the list yourself:
var imgs = document.getElementsByTagName('img');
for( var i = 0; i < imgs.length; i++ ) {
parent.appendChild( imgs[i] );
}
i am using a for loop to generate paragraph tags based on the length of my array. I want each of these p tags generated to have the same innerHTML. I can get the tags to generate with the class name but the innerHTML remains blank.
I have tried the following to no avail, not sure what I am doing wrong.
for (i = 0; i < numArray.length; i++) {
var line = document.createElement("p");
line.className = "line";
document.body.appendChild(line);
var b = document.getElementsByClassName("line");
b.innerHTML = "|";
}
You don't need to call getElementsByClassName you can change the innerHTML of line since you already have the reference to the DOM element.
for (i = 0; i < numArray.length; i++) {
var line = document.createElement("p");
line.className = "line";
line.innerHTML = "|";
document.body.appendChild(line);
}
And explaining why it didn't work, it's because getElementsByClassName returns a collecion of elements, you need to loop through them.
getElementsByClassName should return an array of elements, not a single element. You could try: getElementsByClassName('line')[i], if there is some reason you are doing that specifically.
Note: getElementsByClassName('line')[i] may not refer to the object you just created, unless there are no other "line"s on the page. It scans the document for all elements that have a class called line, which could be paragraphs or other element types.
For a better alternative, please refer to changes made below. This:
caches the numArray length into a variable, so you are not performing that operation at each loop iteration
sets the HTML and ClassName of the element you created before attaching it to the document; which has a number of performance benefits
does not unnecessarily do a DOM lookup for elements, which is expensive
uses the var keyword to avoid scoping conflicts for loop variables
JS Fiddle:
for ( var i=0, n=numArray.length; i < n; i++) {
var line = document.createElement("p");
line.className = "line";
line.innerHTML = '|';
document.body.appendChild(line);
}
I have a jQuery plugin that I want to convert into pure javascript, so that I can drop the dependency on jQuery. The part of the plugin i'm stuck on is this bit, which returns the DOM elements sorted by depth (eg. body's children, then grandchildren, then great-grand-children, etc etc)
var first = $('body'),
output = [];
while(first.length != 0) {
output = $.merge(output, first);
first = first.children();
}
basically I just need the pure javascript version of $('body') , $.merge and children() to help me on my way.
Any help would be much appreciated
Ok, I figured it out myself, it was pretty simple in the end.
// Every Element in the DOM.
var allElements = document.getElementsByTagName('*'),
// All the Element's children sorted by depth,
// ie. body, then body's children, grandchildren,
// so on and so forth.
sortedByDepth = [];
// for every element
for(var i = 0; i<allElements.length; ++i) {
// grab Its children
var allChildren = allElements[i].children;
// for every grabbed child
for(var j = 0; j<allChildren.length; ++j){
// Add it to the sortedByDepth array
sortedByDepth = sortedByDepth.concat(allChildren[j]);
}
}
console.log(sortedByDepth);
I'm writing a javascript function where I get a ul object from my HTML and want to set the text of one of the li elements in theul`. I'm doing:
list = document.getElementById('list_name');
Then I want to access the ith li element of list using a loop.
I have:
for (i = 0; i < 5; i++) {
list[i].innerHTML = "<a>text</a>";
}
but this is not working. What is the proper way to do it?
You need to access the child li elements of the ul. JavaScript and the DOM API can't automagically do that for you.
var list = document.getElementById('list_name'),
items = list.childNodes;
for (var i = 0, length = childNodes.length; i < length; i++)
{
if (items[i].nodeType != 1) {
continue;
}
items[i].innerHTML = "<a>text</a>";
}
You could also use getElementsByTagName('li') but it will get all descendent li elements, and it seems you want only the direct descendants.
You could also avoid innerHTML if you want.
var a = document.createElement('a'),
text = document.createTextNode('text');
a.appendChild(text);
items[i].appendChild(a);
innerHTML can cause issues, such as lost event handlers and the performance issue of serialising and re-parsing the HTML structure. This should be negligible in your example, however.
jQuery Sample code, although the others work:
$("#list_name li").text("<a href=''>text</a>");
Its much more succinct with jQuery
You can try the following
var el = document.createElement("li"),
content = document.createTextNode("My sample text"),
myUl = document.getElementById("ulOne");
el.appendChild(content);
el.id = "bar";
myUl.appendChild(el);
Here's the demo: http://jsfiddle.net/x32j00h5/
I prefer a aproach using getElemenetByTagName, if somehow you get a extra node like a script tag or a span you will have problems. A guess this code will help you:
var list = document.getElementById("mylist");
var items = list.getElementsByTagName("li");
for(var i = 0, size = items.length; i< size; i++){
items[i].innerHTML = "<a href='#'>LINK</a>";
}