Change all <p> elements with a class to <code> - javascript

This is working fine using the document.getElementsByID, but how do you change all the p tags with a prgrph class to code so that instead of <p class="prgrph"></p> there will be <code class="prgrph"></code>?
var b = document.querySelectorAll('p');
for (var i = 0; i < b.length; i++) {
b[i].setAttribute('id', 'prgrph');
}
But this is not working:
function changeTagName(el, newTagName) {
var n = document.createElement(newTagName);
var attr = el.attributes;
for (var i = 0, len = attr.length; i < len; ++i) {
n.setAttribute(attr[i].name, attr[i].value);
}
n.innerHTML = el.innerHTML;
el.parentNode.replaceChild(n, el);
}
changeTagName(document.getElementsByClassName('prgrph'), 'code');
I tried to use document.getElementsByClassName and it's giving me error on the attr.length:
Uncaught TypeError: Cannot read property 'length' of undefined

IDs need to be unique and you likely want to change the P tags one by one
I am not sure why you first loop over the P tags and then loop again; the first loop is not really needed if the second loop selects the P tag instead of the class
var b = document.querySelectorAll('p');
for (var i = 0; i < b.length; i++) {
b[i].classList.add('prgrph');
}
function changeTagName(el, newTagName) {
var n = document.createElement(newTagName);
var attr = el.attributes;
for (var i = 0, len = attr.length; i < len; ++i) {
n.setAttribute(attr[i].name, attr[i].value);
}
n.innerHTML = el.innerHTML;
el.parentNode.replaceChild(n, el);
}
document.querySelectorAll(".prgrph").forEach(function(p) { // not IE
changeTagName(p, 'code');
})
code {
color: red
}
<p data-attr="one">Paragraph 1</p>
<p data-attr="two">Paragraph 2</p>
<p>Paragraph 3</p>

Related

unable to delete random array elements on onclick event

I have an array and displaying its content wrapped up in a P tag on the body, now how do I delete the element when I click on the specific element.
JS:
var arr = [10, 20, 30];
var demo = document.getElementById('demo');
for( var i = 0; i < arr.length; i++) {
demo.innerHTML += `<p class="tag">${arr[i]} </p>`;
}
var pTag = document.getElementsByClassName("tag");
for( var j = 0; j < pTag.length; j++) {
pTag[j].onclick = function() {
arr.splice(pTag[j], 1);
}
}
Use array methods instead - don't use var with asynchronous code, since it gets hoisted and has function scope instead of block scope.
const arr = [10, 20, 30, 40, 50];
const demo = document.getElementById('demo');
arr.forEach(num => {
const p = demo.appendChild(document.createElement('p'));
p.textContent = num;
p.addEventListener('click', () => {
arr.splice(arr.indexOf(num), 1);
p.remove();
console.log('now have ' + JSON.stringify(arr));
});
});
<div id="demo">
</div>
I'd recommend avoiding getElementsByClassName. The getElementsBy* methods return HTMLCollections, which can be difficult to work with. Consider using querySelectorAll instead, which returns a static NodeList - unlike an HTMLCollection, it can be iterated over directly, it won't change while it's being iterated over, and it's much more flexible.
Here is what you could do.
var arr = [10, 20, 30];
var demo = document.querySelector('#demo');
for (var i = 0; i < arr.length; i++) {
demo.innerHTML += `<p class="tag">${arr[i]} </p>`;
}
demo.addEventListener('click', function(event) {
event.target.remove();
});
<div id='demo'>
</div>
Modifying you code, I have came up with this:
var arr = [10, 20, 30];
var demo = document.getElementById('demo');
for (var i = 0; i < arr.length; i++) {
demo.innerHTML += `<p class="tag">${arr[i]} </p>`;
}
var pTag = document.getElementsByClassName("tag");
for (var j = 0; j < pTag.length; j++) {
pTag[j].onclick = function() {
console.log(this.innerText);
this.remove();
var num = parseInt(this.innerText);
arr.splice(arr.indexOf(num), 1);
console.log(arr)
}
}
<div id="demo">
</div>

Looping through a set of <p>'s one at a time

I'm trying to figure out how to count the number of p's so every time the button is pressed, it outputs to 0 to 1 until the maximum number of p's is counted.
var big_number = 999999;
var i;
var a = document.getElementsByTagName("p");
function function0() {
for (i=0; i < big_number; i++) {
document.getElementsByTagName("p")[i].innerHTML="text";
}
}
I want it to write to another p every time the button is pressed.
document.getElementsByTagName("p").length // number of p elements on the page
Is that what you were asking?
Make a generic tag adder function then call it:
function addTags(tagName,start, max, container) {
var i = start;
for (i; i < max; i++) {
var newp = document.createElement(tagName);
newp.innerHTML = "paragraph" + i;
container.appendChild(newp);
}
}
var tag = 'p';
var big_number = 30;
var i;
var a = document.getElementsByTagName(tag );
// **THIS is your specific question answer**:
var pCount = a.length;
var parent = document.getElementById('mydiv');
addTags(tag,pCount , big_number, parent);
// add 10 more
a = document.getElementsByTagName(tag );
pCount = a.length;
big_number = big_number+10;
addTags(tag,pCount , big_number, parent);
EDIT:
NOTE: THIS might be better, only hitting the DOM once, up to you to determine need:
function addTagGroup(tagName, start, max, container) {
var tempContainer = document.createDocumentFragment();
var i = start;
for (i; i < max; i++) {
var el = document.createElement(tagName);
el.textContent = "Paragraph" + i;
tempContainer.appendChild(el);
}
container.appendChild(tempContainer);
}
To find out how many <p> elements there are in the document you should use DOM's length property as below :-
var numP = document.getElementsByTagName("P").length;
or
var div = document.getElementById("myDIV");
var numP = div.getElementsByTagName("P").length;
To get number of element inside a tag.

How to remove children in JavaScript

What is the equivalent of the following JQuery code in JavaScript:
$('div').children().remove();
I tried following but it says length is not defined:
var nodes = document.getElementsByTagName('div').childNodes;
for(var i=0; i< nodes.length; i++) {
nodes[i].remove();
}
Fiddle
The correct cross-browser way to remove elements in pure JavaScript is:
element.parentNode.removeChild(element);
So following your example the solution is this:
var nodes = document.getElementsByTagName('div');
for (var i = 0, len = nodes.length; i < len; i++) {
var node = nodes[i],
children = node.childNodes;
for (var j = children.length; j--;) {
node.removeChild(children[j]);
}
}
However, better option to remove all children is to do it in while loop:
var nodes = document.getElementsByTagName('div');
for (var i = 0, len = nodes.length; i < len; i++) {
var node = nodes[i];
while (node.firstChild) {
node.removeChild(node.firstChild);
}
}
DEMO: http://jsfiddle.net/N6RM4/1/
Check document.getElementsByTagName('div')
It returns a NodeList
This has no member called childNodes
To remove all childnodes of all divs, you need to iterate over these nodes.
This is a working example
HTML
<button id="adds" onclick="add()">add</button>
<button id="removes" onclick="del()">remove</button>
<form>
<div id="myList">
<div><input type="checkbox"></div>
</div>
</form>
JS
function del(){
var list=document.getElementById("myList");
if (list.childNodes.length > 2){
list.removeChild(list.childNodes[list.childNodes.length-1]);
}
}
function add(){
var par=document.createElement("div");
var chi = document.createElement('div');
chi.innerHTML = '<input type="checkbox"></input>';
par.appendChild(chi);
document.getElementById("myList").appendChild(par);
}
getElementsByTagName returns a element-list and you have to specify the index (in your case [0])
var nodes = document.getElementsByTagName('div')[0].childNodes;
JSfiddle

Hiding a table row for a cell containing a span

I am trying to hide a row which contains in one of the cells a specific span element. The following code is what I have so far - but there is no getElementsByTagName for a tr
What else can I do to get the row? Thanks !
<table id='tableContainer'>
<tr><td><span id='xyz'>Hide</span></td></tr>
<tr><td><span id='abc'>Show</span></td></tr>
</table>
container = document.getElementById('tableContainer');
items = container.getElementsByTagName('tr');
for (var j = 0; j < items.length; j++) {
spans = items.getElementsByTagName('span');
for (var i=0; i<spans.length; i++) {
if (spans.id == 'xyz') {
items.display = 'none';
}
}
}
spans and items are arrays of nodes, so you forgot to get each one by array index, it should be like this,
<table id='tableContainer'>
<tr><td><span id='xyz'>Hide</span></td></tr>
<tr><td><span id='abc'>Show</span></td></tr>
</table>
container = document.getElementById('tableContainer');
items = container.getElementsByTagName('tr');
for (var j = 0; j < items.length; j++) {
spans = items[j].getElementsByTagName('span');
for (var i=0; i<spans.length; i++) {
if (spans[i].id == 'xyz') {
items[j].style.display = 'none';
}
}
}
DEMO
UPDATE:
And don't forget to put style before display.
items[j].display = 'none'; // false
items[j].style.display = 'none'; // true
So let us debug a little:
container = document.getElementById('tableContainer');
console.log(container) //<-- Gives you tag element
items = container.getElementsByTagName('tr');
console.log(items); //<-- Gives you HTML Collection
for (var j = 0; j < items.length; j++) {
spans = items.getElementsByTagName('span'); //<-- error says items.getElementsByTagName is not a function
for (var i=0; i<spans.length; i++) {
if (spans.id == 'xyz') { //<--error here [not referencing index]
items.display = 'none'; //<--error here [not setting style and index]
}
}
}
Problem here is you are not indexing each tr, you are trying to run it on the whole html collection.
spans = items.getElementsByTagName('span');
should be
spans = items[j].getElementsByTagName('span');
You need to do the same thing in the spans loop so the final code would be
container = document.getElementById('tableContainer');
console.log(container) //<-- Gives you tag element
items = container.getElementsByTagName('tr');
console.log(items); //<-- Gives you HTML Collection
for (var j = 0; j < items.length; j++) {
spans = items[j].getElementsByTagName('span'); //<-- use index
items.getElementsByTagName is not a function
for (var i=0; i<spans.length; i++) {
console.log(spans[i].id)
if (spans[i].id == 'xyz') { //<-- use index
items[j].style.display = 'none'; //<-- use index and display
}
}
}
Running example: JSFiddle

Script only changes first <p> element

Below is the javascript I have for my page:
window.onmouseover = function(){
var body = document.getElementsByTagName("body")
var h1 = document.getElementsByTagName("h1");
var a = document.getElementsByTagName("a");
var p = document.getElementsByTagName("p")
for(var j = 0; j < p.length; j++) {
body[j].style.fontFamily = "helvetica";
body[j].style.backgroundColor = "rgb(250, 250, 240)"
p[j].style.fontFamily = "courier";
a[j].onclick = function() {
this.style.backgroundColor = "Black"
}
}
}
I have one h1 element, one a element, and 10 p elements. For some reason, this code only changes the font of the first p element, although everything else works fine? Why is this and how can I fix it?
If you have only one a element and (of course) only one body you cannot iterate over 10 of them. This causes an error on the second iteration of the cycle. Use this code instead.
window.onmouseover = function(){
var body = document.getElementsByTagName("body")
var h1 = document.getElementsByTagName("h1");
var a = document.getElementsByTagName("a");
var p = document.getElementsByTagName("p")
body[0].style.fontFamily = "helvetica";
body[0].style.backgroundColor = "rgb(250, 250, 240)"
a[0].onclick = function() {
this.style.backgroundColor = "Black"
}
for (var j = 0; j < p.length; j++) {
p[j].style.fontFamily = "courier";
}
}
It may be generating an error the second time through the loop, since body[1] would be invalid. Move things around so that only manipulations on p are inside the loop.

Categories

Resources