so I will preface my question with letting you know that this is an assignment for school. I have been working to solve this and I have tried to find the solution within the MDN documentation and I am at a loss. I have to:
Grab a NodeList of bugs
Convert the NodeList to an Array
Here is my index.html file:
<!DOCTYPE html>
<html>
<head>
<title>Bugs in the DOM</title>
</head>
<body>
<div>
<h1>Bugs in the DOM</h1>
<ul>
<li>Horse Flies</li>
<li>Bed bugs</li>
<li>Mosquito</li>
<li>Ants</li>
<li>Mites</li>
<li>Cricket</li>
<li>Woolly Bear Caterpillar</li>
<li>Fleas</li>
<li>Worms</li>
<li>Leeches</li>
</ul>
</div>
<script>
(function() {
// Your code here.
}());
</script>
</body>
</html>
I have been able to grab the li elements, while using the DOM with the following code:
var list = document.getElementsByTagName("ul");
When i call list in the DOM, I am returned the ul, which contains all of the li elements. Not sure if that is what I am supposed to do with respect to the NodeList. I am also confused as to how I can convert the NodeList to an array. Not sure if I need to use a for loop and append each element of the NodeList into a new array? This is all still very new and confusing to me.
Any help is much appreciated, but if you are willing to share insight and an explanation, that would be ideal. I am really trying to wrap my mind around this and I am falling short. Thank you in advance!
You can iterate all the <li> items in each <ul> in the page like this while able to separately tell which <ul> they are in:
var list = document.getElementsByTagName("ul");
for (var i = 0; i < list.length; i++) {
var items = list[i].getElementsByTagName("li");
for (var j = 0; j < items.length; j++) {
console.log(items[j]);
}
}
Or, if you just want all <li> tags, not broken out by <ul>:
var items = document.getElementsByTagName("li");
for (var i = 0; i < items.length; i++) {
console.log(items[i]);
}
A nodeList or HTMLCollection can be iterated with a simple for loop as seen above. These objects do not have array methods, but can be copied into an array if you really want to use array methods.
Note, it is probably simpler to use document.querySelectorAll() for listing all the <li> elements and you may want to target a specific <ul> tag by putting an id on it in case there are other <ul> and <li> elements in the page.
<ul id="buglist">
<li>Horse Flies</li>
<li>Bed bugs</li>
<li>Mosquito</li>
<li>Ants</li>
<li>Mites</li>
<li>Cricket</li>
<li>Woolly Bear Caterpillar</li>
<li>Fleas</li>
<li>Worms</li>
<li>Leeches</li>
</ul>
var items = document.querySelectorAll("#buglist li");
for (var j = 0; j < items.length; j++) {
console.log(items[j]);
}
A nodeList or HTMLCollection can be copied into an array like this:
var list = Array.prototype.slice.call(document.querySelectorAll("#buglist li"), 0);
list.forEach(function(item) {
console.log(item);
});
Related
I would like to set id attributes for all the DOM elements by default. The IMPORTANT point is that it should happen during the construction of elements (when the browser is parsing HTML code and creating HTML elements and before appending them to the DOM tree). For example, if the HTML code of my website is like this:
<html>
<head>
<script>
//overriding constructor of Element
</script>
</head>
<body>
<p id='nH6Rf72Jk'> This is a paragraph </p>
<p> This is another paragraph </p>
</body>
</html>
I would like to have an id attribute (a random value) even for elements that do not explicitly an id has specified for them. I think it might be possible by overriding constructor of the Element interface (by the script that exists in the head). In other words, while browser is generating the elements and appending them to the DOM tree, check the id attribute; if it doesn't exist, generate a random value and set it as the id. Does anyone know if is possible to override the Element constructor? Or is there any other solution for this problem?
This should work
let all = document.getElementsByTagName("*");
for (let i=0; i < all.length; i++) {
if(all[i].getAttribute('id') === null){
all[i].setAttribute('id', makeId(6));
}
}
function makeId(length) {
let finalStr = '';
let chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var charsLength = chars.length;
for (i = 0; i < length; i++ ) {
finalStr += chars.charAt(Math.floor(Math.random() * charsLength));
}
return finalStr;
}
document.addEventListener('DOMContentLoaded', () => {
let elements = document.querySelectorAll('body *');
elements.forEach((elem => {
if (!elem.getAttribute('id')) {
elem.setAttribute('id', btoa(window.crypto.getRandomValues(new Uint32Array(1))[0]));
}
}));
});
I am new with js and playing with replace method.
I have had no problems when replacing string for another string etc., but when im trying to do same with tags nothing happens..
Im trying to replace every tags for -tags. My function is below:
function bonus() {
var list = document.getElementsByTagName('li');
for (var i = 0; i < list.length; i++) {
newList = document.getElementsByTagName('li')[i].innerHTML;
newList = newList.replace('<li>', '<strong>');
newList = newList.replace('</li>', '</strong>');
document.getElementsByTagName('li')[i].innerHTML = (newList);
//console.log(newList);
}
}
function bonus(){
var list=document.getElementsByTagName('li');
var len = list.length;
for(var i=len-1; i>-1; i--){
var tmpItem = list[i]
newList = tmpItem.outerHTML;
newList = newList.replace('<li>','<strong>');
newList = newList.replace('</li>','</strong>');
tmpItem.outerHTML = newList;
}
}
I thought you might change your code like above, and there was still much space to optimize your code. go ahead <( ̄︶ ̄)>
First of all you should never replace a list-item with another element like that. A list item must always be a child of an ul or ol elelment, and ul and ol elements should not have any other immediate child that isn't a li.
However, this doesn't work because the li is an html element and not a text string and the inner HTML of an html elemnt doesn't contain the tag itself. It may contain children and those children's tags are part of the innerHTML, everything inside the element/tag itself is the innerHTML.
An example to clarify:
<ul>
<li>one<strong>second one</strong></li>
<li>two<strong>second two</strong></li>
<li>three<strong>second three</strong></li>
<li>four</li>
</ul>
Looping through all list items accessing elements as you've describe
for(var i=0; i<list.length;i++) {
console.log("==>> " + document.getElementsByTagName("li")[i].innerHTML);
}
Will output the following to the console:
==>> one<strong>second one</strong>
==>> two<strong>second two</strong>
==>> three<strong>second three</strong>
==>> four
If you want to make all li elements strong they should be nested as this:
<li><strong>Some text</strong></li>
To Achieve this one way to do it would be:
var list = document.getElementsByTagName("li");
for(var i=0; i<list.length; i++) {
var listItem = list[i];
listItem.innerHTML = "<strong>" + listItem.innerHTML + "</strong>";
}
If you want to convert all li elements to strong elements you must first remove them from the list...
Thanks alot for all of you. I knew that i can't change li for strong in real world, but i just tried to figure out if its possible to do so with simple loop.
My example html is full of lists, so thats why i used li instead of h2 to h3 or something like that. Outer html was new thing for me, and solution for this one. However Kim Annikas answer helped me with other question about modifying lists: I did this:
function replace(){
var list=document.getElementsByTagName('li');
for(var i=0;i<list.length;i++){
newText="<strong>Replaced!</strong>";
var listItem=list[i];
listItem.style.color="red";
listItem.innerHTML=newText;
}
}
..and now it seems that i have learnt how to modify tags as well as text inside of it ;)
This question already has answers here:
JavaScript DOM remove element
(4 answers)
Closed 8 years ago.
I have a code:
<ul class='mates'>
<li class='m' id='1'>Jakub</li>
<li class='f' id='2'>Vinnie</li>
<li class='m' id='3'>David</li>
</ul>
This script selects one of the 'li' elements, according to users input:
<script>
var mates = document.getElementsByClassName('mates')[0];
for (var i=0; i< mates.childNodes.length; i++){
if(mates.children[i].innerHTML == 'Vinnie') alert("Got you! ID "+mates.children[i].id)
}
</script>
And I need to remove this element:
<script>
var mates = document.getElementsByClassName('mates')[0];
for (var i=0; i< mates.childNodes.length; i++){
if(mates.children[i].innerHTML == 'Vinnie') {
alert("Got you! ID "+mates.children[i].id);
parent = document.getElementsByClassName('mates');
mateToDelete = mates.children[i];
parent.removeChild(mateToDelete);
}
}
</script>
This is what I tried in several different ways but I always got error, e.g. " Cannot call method 'removeChild' of undefined". Any ideas?
You already have the parent node from your original getElementsByClassName, and you have your child through the loop that you've just performed.
As such, it's simple:
for (var i=0; i< mates.childNodes.length; i++){
if(mates.children[i].innerHTML == 'Vinnie'){
alert("Got you! ID "+mates.children[i].id)
mates.removeChild(mates.children[i]);
break;
}
}
For the sake of completeness (and to prevent further arguing in comments :P), if you are in fact potentially deleting multiple "Vinnie"'s from your list, then it would be better to make a list of those children you want to delete, then delete them after like so:
var toDelete=[],
i;
for (i=0; i< mates.childNodes.length; i++){
if(mates.children[i].innerHTML == 'Vinnie'){
alert("Got you! ID "+mates.children[i].id)
toDelete.push(mates.children[i]);
}
}
for (i=0; i<toDelete.length; i++){
mates.removeChild(toDelete[i]);
}
You don't need that parent variable. Delete it using this:
mates.removeChild(mateToDelete);
Fiddle: http://jsfiddle.net/3XeM5/2/
I also modified your for-loop to use:
for (var i=0; i< mates.children.length; i++){
The length of this (children.length) is 3, the length of childNodes is 7, so if nothing is found the loop will break!
Edit: If you want to delete multiple iterations of a specific element, remove the break; in the if-logic. If you're only looking for the first, leave the break.
Use This:
mates.removeChild(mates.children[i]);
Example:
http://jsfiddle.net/t9nCT/1/
You're retrieving a collection, so do,
parent[0].removeChild(mateToDelete);
I've got some code in html like
<li id="1"></li>
<li id="2">Whatever</li>
<li id="3"></li>
Is there any way I can make it so that if the li contains a piece of text, it won't be displayed, yet all the other lis will be unaffected?
You could loop through your lis and use document.getElementById(id).innerHTML to get the value inside it to compare to, and if so, use document.getElementById(id).style.display = 'none';
var list = document.getElementsByTagName("li");
for(var i = 0; i < list.length; i++){
if(list[i].textContent === "Whatever"){
list[i].style.display = "none";
}
}
Live Demo
Here's a couple of examples using exact/non-exact matches, case-sensitive and insensitive.
http://jsfiddle.net/ZgrzL/
Edit: wow, I'm slow.
I'm trying to change the name of a link, however, I have some restrictions. The link is placed in code that looks like this:
<li class='time'>
Review Time
<img alt="Styled" src="blah" />
</li>
Basically, I have a class name to work with. I'm not allowed to edit anything in these lines, and I only have a header/footer to write Javascript / CSS in. I'm trying to get Review Time to show up as Time Review, for example.
I know that I can hide it by using .time{ display: hide} in CSS, but I can't figure out a way to replace the text. The text is also a link, as shown. I've tried a variety of replace functions and such in JS, but I'm either doing it wrong, or it doesn't work.
Any help would be appreciated.
You could get the child elements of the li that has the class name you are looking for, and then change the innerHTML of the anchor tags that you find.
For example:
var elements = document.getElementsByClassName("time")[0].getElementsByTagName("a");
for(var i = 0, j = elements.length; i<j; i++){
elements[i].innerHTML = "Time Review";
}
Of course, this assumes that there is one element named "time" on the page. You would also need to be careful about checking for nulls.
Split the words on space, reverse the order, put back together.
var j = $('li.time > a');
var t = j.text();
var a = t.split(' ');
var r = a.reverse();
j.text(r.join(' '));
This could have some nasty consequences in a multilingual situation.
Old school JavaScript:
function replaceLinkText(className, newContents) {
var items = document.getElementsByTagName('LI');
for (var i=0; i<items.length; i++) {
if (items[i].className == className) {
var a = items[i].getElementsByTagName('A');
if (a[0]) a[0].innerHTML = newContents;
}
}
}
replaceLinkText("time", "Review Time");
Note that modern browsers support getElementsByClassName(), which could simplify things a bit.
You can traverse the DOM and modify the Text with the following JavaScript:
var li = document.getElementsByClassName('time');
for (var i = 0; i < li.length; i++) {
li[i].getElementsByTagName('a')[0].innerText = 'new text';
}
Demo: http://jsfiddle.net/KFA58/