Create elements using function parameters, Javascript - javascript

First time question asker, go easy on me. I think I've thoroughly looked through Stack so as to not ask a repeated question.
I have a function.
function createDivs(num) {
for(let inc = 0; inc < num; inc++) {
let div = document.createElement('div'),
tab_content = document.getElementsByClassName('tab-content');
div.className = 'classname';
div.id = `number-${inc}`;
div.innerHTML = 'did it work?';
tab_content.innerHTML = div;
}
}
Where the HTML is just simply
<div class="tab-content">
<script>
createDivs(4);
</script>
</div>
I've tried other methods like
let tab_content = document.getElementsByClassName('tab-content');
tab_content.innerHTML = '<div class="classname" id=`number-${inc}`>did it work?</div>';
as well as ton other variations with the '' "" and `` and that didn't work neither.
I have also tried tab_content.appendChild(div); and that didn't work either.
In reality this is a downgrade of what my actual code is because I'm creating tons of elements that need things in them, but I can't even get this bit to work. It doesn't even work if I remove the for loop. Also I did see this post, hence why I tried the appendChild, but again that also didn't work.

It looks to me like you want not to set the innerHTML, but actually to append several child nodes. In addition to that, there were a couple of errors in your code (getElementsByClassName) returns an array-like object, not just one object, so you'll need to select one to add your divs to.
Also, you named your i variable in the loop inc not i, so it doesn't actually increment the loop. Take a look at the below rewritten code and see if that does what you're looking for.
function createDivs(num) {
for(let inc = 0; inc < num; inc++) {
let div = document.createElement('div'),
tab_content = document.getElementsByClassName('tab-content');
div.className = 'classname';
div.id = `number-${inc}`;
div.innerHTML = 'did it work?';
tab_content[0].appendChild(div);
}
}
(function(){createDivs(4)})()
<div class="tab-content">
</div>

You had a few typos in your code. usin i++ instead of inc++ in your loop. Not accessing tab_content as an array and using innerHtml instead of appendChild. Fixed code is below.
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
function createDivs(num) {
for(let inc = 0; inc < num; inc++) {
let div = document.createElement('div'),
tab_content = document.getElementsByClassName('tab-content')[0];
div.className = 'classname';
div.id = `number-${inc}`;
div.innerHTML = 'did it work?';
tab_content.appendChild(div);
}
}
</script>
</head>
<body>
<div class="tab-content">
<script>
createDivs(4);
</script>
</div>
</body>
</html>

your for loop does not increment its control variable. Change it to
for(let inc = 0; inc < num; inc++) {
and getElementsByClassName returns an array like object, not a single element. So you need to change it to
tab_content = document.getElementsByClassName('tab-content')[0];

Related

Change inline css of an element without an id or class

It's pretty simple to change the style of an element when it has a class. I thought it would be simple to change the style of an element that has no class or id too, but I haven't been able to figure it out.
The html page looks something like this:
<!DOCTYPE html>
<html>
<head>
<title>ExamplePage</title>
</head>
<body>
<h1>Lorem ipsum</h1>
<p style="display: none">The style shouldn't change</p>
<section class="container_class">
<p style="display: none">The display part of the inline css should be deleted or modified to inline</p>
<p style="display: none">The display part of the inline css should be deleted or modified to inline</p>
<p style="display: none">The display part of the inline css should be deleted or modified to inline</p>
</section>
<p style="display: none">The style shouldn't change</p>
</body>
</html>
Since I'm trying to build a google chrome extension I've been using contentscripts.
I haven't figured out how to select the specific element although I have seen something similar to this idea.
I've searched the internet on how to select a specific element based on the inline css. I couldn't find anything helpful.
This is my content.js:
var ps = document.querySelectorAll("section.container_class > p");
var i;
for (i = 0; i < ps.length; i++) {
ps.style.display = "inline";
}
I'm new to coding in javascript, so the code might not make sense at all. It's just an idea on how to change the inline css. I'm trying to learn by doing a mini-project like this.
You're nearly there.
The bug is in the for loop. It should be:
var ps = document.querySelectorAll("section.container_class > p");
var i;
for (i = 0; i < ps.length; i++) {
ps[i].style.display = "inline";
}
Note the square bracket array access notation on the ps variable.
ie. for every iteration of the loop, access the ith index of the array ps.
"document.querySelectorAll" returns an Array containing all the elements that you have specified (in this case: "section.container_class > p"). So when you want to iterate through the entire Array you will have to use an index.
Basically all you forgot was to add [i] in your block of code.
var ps = document.querySelectorAll("section.container_class > p");
var i;
for (i = 0; i < ps.length; i++) {
ps[i].style.display = "inline";
}
However you should try to use the let and const keywords instead of var.
Also i is defined as a global variable and you don't want that because it might interfer with locally defined variables. So instead you should declare it in the for-loop "head".
A newer version might look something like this:
const PS = document.querySelectorAll("section.container_class > p");
for (let i = 0; i < ps.length; i++) ps[i].style.display = "inline";
var ps is defined to array as it selected for querySelectorAll. Seems there is no number for ps array in for loop.
var ps = document.querySelectorAll("section.container_class > p");
var i;
for (i = 0; i < ps.length; i++) {
//Here should be array num.
ps[i].style.display = "inline";
}

change events stop working when a new change event is added to a different element in JS

I am programmatically generating some HTML, and trying to add a listener for a change event the elements.
This works fine for the first object, but as soon as I add the second object the first one stops firing the event.
In the code example below you'll see the updateLabel function only fires for the last object created. I need it to fire for all of the objects.
I have tried with .onchange, and with an event listener, but get the same results.
Any help much appreciated.
<html>
<body>
<div id="main">
<!--this is where all the generated HTML goes -->
</div>
</body>
<script>
mainDomElement = document.querySelector("#main");
for (var count = 0; count < 4; count++)
{
var labelId = 'Label' + count;
newHTML = '<input class="accordionLabel" type="text" id="' + labelId + '" value="' + labelId + '"/>'
currentHTML = mainDomElement.innerHTML
mainDomElement.innerHTML = newHTML + currentHTML
labelDomObj = document.querySelector('#' + labelId);
//labelDomObj.addEventListener("change", updateLabel);
labelDomObj.onchange = function(event){updateLabel(event)}
}
function updateLabel(event)
{
alert(event.target.value);
}
</script>
</html>
It may be best to take a different approach when creating and adding DOM elements. Try this.
for (var count = 0; count < 4; count++)
{
var labelId = 'Label' + count,
newHTML = document.createElement('input');
newHTML.type = 'text';
newHTML.value = labelId;
newHTML.id = labelId;
newHTML.addEventListener('onchange', updateLabel, false);
mainDomElement.appendChild(newHTML);
}
your code explanation
// this takes the main DOM element and stores a copy of it in the variable.
currentHTML = mainDomElement.innerHTML
/*
This is taking the innerHTML property of the main DOM element. It is then
trying to concatenate the newly created DOM to that stored in the mainDomElement
variable. I don’t think this is what you want.
*/
mainDomElement.innerHTML = newHTML + currentHTML
// this is trying to select an element from the DOM that does not exist yet.
labelDomObj = document.querySelector('#' + labelId);
// This is trying to add an event listener to an element that does not exist.
labelDomObj.onchange = function(event){updateLabel(event)}
You are also missing sim icons from your variable declarations.
This looks like an issue with closures, where initializing var count = 0 within the for loop ultimately results in only the last value getting bound to the event handler.
I believe moving the initialization outside of the loop will fix your issue. Also, ES6 introduced the let keyword that scopes the variable in the way you are expecting:
for (let count = 0; count < 4; count++) { }
See this excellent introduction to javascript closures for more information.

Change color for every second ul li with a "for loop"

I am learning javascript in codecademy and so far I understand how alot of things work. Sadly they dont explain how to target an elements color or how to target elements / selectors / divs.
I am testing out my knowledge. What I am trying is to give every second list item the color red by using the for loop.
How do I do this?
var listColor = function(){
var color = style.("red");
var list = getElementsByTagName("li");
for (i = 0; i < list.length; i + 2;) {
list === color
}
];
listColor();
and here my http://jsfiddle.net/Lr8nZ/15/
UPDATED JSfiddle but still not working http://jsfiddle.net/Lr8nZ/23/
so basically:
Red,
Black,
Red,
Black
Something do like this.
var listColor = function(){
var list = document.getElementsByTagName("li");
for (i = 0; i < list.length; i++) {
if(i%2==0)
list[i].style="color:red";
else
list[i].style="color:blue";
}
}
listColor();
You have a few syntax errors, but you can do this:
var listColor = function() {
var list = document.getElementsByTagName('li');
for (var i = 0, l = list.length; i < l; i++) {
if (i % 2 === 0) {
list[i].style.color = 'red';
}
}
};
// Or...
var listColor = function() {
var list = document.getElementsByTagName('li');
for (var i = 0, l = list.length; i < l; i += 2) {
list[i + 1].style.color = 'red';
}
};
listColor();
When you increment i make sure you're updating its value with i++ or i += 1, or you'll create an endless loop.
i % 2 uses the % modulus operator. It's the remainder you would get from dividing the two numbers. Even numbers divide evenly by 2, so the remainder will be 0, which we check for.
The property you were looking for is called style. It has a property called color which we set to the string 'red' in this case.
try this
<html>
<head>
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
index=1;
$("#temp li").each(function(){
if(index%2==0)
{
$(this).css("color","red")
}
index++;
});
})
</script>
<style>
</style>
</head>
<body>
<ul id='temp'>
<li>One</li>
<li>Two</li>
<li>Three</li>
<li>Four</li>
</ul>
</body>
</html>
Try using a console to see the errors in your code. It's a tool that's indispensible for any js coder. Here's the updated fiddle http://jsfiddle.net/Lr8nZ/24/
The first thing which you notice is style.color('red'). For this line to be even valid js, there has to be a style object defined. Otherwise it will search for it on window which always leads to confusion.
Another thing is note how we have to actually assign the new value to i in for loop' third condition. Just mentioning i+2 will not work because i will stay the same resulting in an infinite loop.
Again, fire up web console. Generally, you do that by right clicking on page > Inspect > Web console.

Getting an element by id every time I loop through

So my issue is, whenever I run this loop, it only grabs the changes to the element on the first flip through. Is there a way to make it make those changes every time?
<script>
for ( i=0; i<5; i++){
document.write('<div id=\"blah\" >text</div>');
var b = document.getElementById("blah");
b.style.width ="200px";
b.style.backgroundColor="yellow";
}
</script>
id has to be unique in a document. hence the issue. The DOM would return only 1 node even if there are multiple matches.
You can do something like this:
for (var i=0; i<5; i++){
var div = '<div class="blah" >text</div>';
div.style.width ="200px";
div.style.backgroundColor="yellow";
document.write(div);
}
I have two ideas to overcome this. The first is to create the element, change its style, and append it.
<script type="text/javascript">
for (var i = 0; i < 5; i++) {
var div = document.createElement("div");
div.style.width = "200px";
div.style.backgroundColor = "yellow";
document.appendChild(div);
}
</script>
The other idea is that you don't need a reference to the DOM element, because you're only changing style, so you can apply the style with CSS. For example:
<style type="text/css">
div.something {
width: 200px;
background-color: yellow;
}
</style>
<script type="text/javascript">
for (var i = 0; i < 5; i++) {
document.write("<div class='something'>text</div>");
// Or use the createElement/appendChild approach from above,
// where you'd need to set the div.className property as "something"
}
</script>
You need to add the element to the DOM to be able to access it later.
for(var i=0;i<5;i++)
{
//I'm not sure if you are just trying to make these changes each iteration
//or create a new element each time. If you are trying to create a new element
//each time. I'd def consider going a diff route i.e. use classes.
var b;
if( i==0 ){
b = document.createElement("DIV");
b.id = "blah";}
else{
b = document.getElementById("blah");}
b.style.width ="200px";
b.style.backgroundColor="yellow";
}

Count how many elements in a div

I have a div with span inside of it. Is there a way of counting how many elements in a div then give it out as a value. For Example there were 5 span in a div then it would count it and alert five. In Javascript please.
Thank you.
If you want the number of descendants, you can use
var element = document.getElementById("theElementId");
var numberOfChildren = element.getElementsByTagName('*').length
But if you want the number of immediate children, use
element.childElementCount
See browser support here: http://help.dottoro.com/ljsfamht.php
or
element.children.length
See browser support here: https://developer.mozilla.org/en-US/docs/DOM/Element.children#Browser_compatibility
You can use this function, it will avoid counting TextNodes.
You can choose to count the children of the children (i.e. recursive)
function getCount(parent, getChildrensChildren){
var relevantChildren = 0;
var children = parent.childNodes.length;
for(var i=0; i < children; i++){
if(parent.childNodes[i].nodeType != 3){
if(getChildrensChildren)
relevantChildren += getCount(parent.childNodes[i],true);
relevantChildren++;
}
}
return relevantChildren;
}
Usage:
var element = document.getElementById("someElement");
alert(getCount(element, false)); // Simply one level
alert(getCount(element, true)); // Get all child node count
Try it out here:
JS Fiddle
Without jQuery:
var element = document.getElementById("theElementId");
var numberOfChildren = element.children.length
With jQuery:
var $element = $(cssSelectocr);
var numberOfChildren = $element.children().length;
Both of this return only immediate children.
i might add just stupid and easy one answer
<div>this is div no. 1</div>
<div>this is div no. 2</div>
<div>this is div no. 3</div>
you can get how many divs in your doc with:
const divs = document.querySelectorAll('div');
console.log(divs.length) // 3
With jQuery; checks only for spans inside a div:
JSFiddle
$(function(){
var numberOfSpans = $('#myDiv').children('span').length;
alert(numberOfSpans);
})();​
With jQuery you can do like this:
var count = $('div').children().length;
alert( count );​​​
Here's a Fiddle: http://jsfiddle.net/dryYq/1/
To count all descendant elements including nested elements in plain javascript, there are several options:
The simplest is probably this:
var count = parentElement.getElementsByTagName("*").length;
If you wanted the freedom to add more logic around what you count, you can recurse through the local tree like this:
function countDescendantElements(parent) {
var node = parent.firstChild, cnt = 0;
while (node) {
if (node.nodeType === 1) {
cnt++;
cnt += countDescendantElements(node);
}
node = node.nextSibling;
}
return(cnt);
}
Working Demo: http://jsfiddle.net/jfriend00/kD73F/
If you just wanted to count direct children (not deeper levels) and only wanted to count element nodes (not text or comment nodes) and wanted wide browser support, you could do this:
function countChildElements(parent) {
var children = parent.childNodes, cnt = 0;
for (var i = 0, len = children.length; i < len; i++) {
if (children[i].nodeType === 1) {
++cnt;
}
}
return(cnt);
}
The easiest way is to select all the span inside the div which will return a nodelist with all the span inside of it...
Then you can alert the length like the example below.
alert(document.querySelectorAll("div span").length)
<div>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
</div>

Categories

Resources