Loop should not break on encountering a invalid statement - javascript

Check out this code...
HTML
<span>TEST </span>
<div style="color:red">COlured div</div>
<div style="color:blue">COlured div</div>
<p style="color:red">Colourful TExt</p>
<p style="color:blue">Colourful TExt</p>
<p style="color:green">Colourful TExt</p>
<p style="color:brown">Colourful TExt</p>
<button onclick="changetobw()">CHANGE COLOR</button>
JavaScript
function changetobw() {
a = document.getElementsByTagName('p');
b = document.getElementsByTagName('div');
var i = 0;
do {
a[i].classList.add('nocolor');
b[i].classList.add('nocolor');
i++;
} while (i < a.length && i < b.length);
}
CSS
.nocolor {
color:#000 !important;
}
DEMO
What i am attempting to do here is on click of the button make all the div and span font color "black".
My code breaks(obviously) when the counter crosses i=2 because there are just 2 div and hence "i[2]" would be undefined and hence the loop breaks.
Is there anyway for the loop not to break after hitting this point? Maybe I am not getting my point perfectly across. Hope you all understand?

To use the loop like you use it, you have to make sure both arrays have the same length.
Obviously, their length isn't equal, so either you seperate this one loop into two loops (1) or you go for two if-statements checking i against the length of both arrays (2). Even better would be using for in combination with the querySelectorAll (3).
(1):
function changetobw() {
a = document.getElementsByTagName('p');
b = document.getElementsByTagName('div');
var i = 0;
do {
a[i].classList.add('nocolor');
i++;
} while (i < a.length);
i = 0;
do {
b[i].classList.add('nocolor');
i++;
} while (i < b.length);
}
(2) (fiddle):
function changetobw() {
a = document.getElementsByTagName('p');
b = document.getElementsByTagName('div');
var i = 0;
do {
if(i < a.length)
a[i].classList.add('nocolor');
if(i < b.length)
b[i].classList.add('nocolor');
i++;
} while (i < a.length || i < b.length);
}
(3) (fiddle):
function changetobw() {
var els = document.querySelectorAll('p, div');
for(var i = 0; i < els.length; i++) {
els.item(i).classList.add("nocolor");
}
}

If you're not worried about browsers beneath IE9, you should use querySelectorAll instead as this will allow you to pick up both types of element in the same query.
var a = document.querySelectorAll('p, div');
for (var i = 0, l = a.length; i < l; i++){
a[i].classList.add('nocolor');
}
Fiddle

I think u should make a specific generic method to change the color and then call it for each tag type u need rather then changing all in one
try this :
function changetobw()
{
changeColor(document.getElementsByTagName('p'));
changeColor(document.getElementsByTagName('div')) ;
}
function changeColor(obj)
{
var i = 0;
do {
obj[i].classList.add('nocolor');
i++;
} while (i < obj.length);
}
demo : http://jsfiddle.net/A52Lj/5/

This do the trick (maybe there is a more elegant solution)
function changetobw() {
a = document.getElementsByTagName('p');
b = document.getElementsByTagName('div');
var i = 0;
do {
a[i].classList.add('nocolor');
i++;
} while (i < a.length);
i = 0;
do {
b[i].classList.add('nocolor');
i++;
} while (i < b.length);
}

Another approach found :
function changetobw() {
a = document.getElementsByTagName('p');
b = document.getElementsByTagName('div');
var j=(a.length>b.length)?a.length:b.length;
var i = 0;
do {
if(i<a.length){
a[i].classList.add('nocolor');
}
if(i<b.length){
b[i].classList.add('nocolor');
}
i++;
} while (i <j);
}

Related

Clone element in a DOM and change the attribute while reusing it in javascript

My code is given below
;(function(window){
var description_window= document.querySelector('.mg_post_description');
var $headings= document.querySelectorAll('.mg_blog_main_content h3');
for (var i = $headings.length - 1; i >= 0; i--) {
description_window.append($headings[i].cloneNode(true));
};
})(window);
Can I change the h3 collected from the 'blog_main_contents' to 'p' tags in the target div.
Thanks and regards
You can iterate through h3's child nodes and append it to new paragraph element:
var paragraph = document.createElement('p');
var headingChildren = $headings[i].cloneNode(true).childNodes;
for (var j = 0; j < headingChildren.length; j++) {
paragraph.appendChild(headingChildren[j]);
}
description_window.append(paragraph);
I used insertAdjecentHtml in this example didnt really need jquery.
for (let i = $headings.length - 1; i >= 0; --i) {
description_window.insertAdjacentHTML("afterbegin","<p>"+ $headings[i].innerHTML + "</p>");
};
Here is a working Example.

p5.js 27646: Uncaught TypeError: Cannot read property '0' of undefined

I was coding in JavaScript, p5.js and came across this error line:
27646: Uncaught TypeError: Cannot read property '0' of undefined
and I don't know what this means since I am not very experienced with JavaScript. It is also suspicious to me because my project does not have line 27646 anywhere.
here is my code:
var particles = [];
const word0 = 'p5.js',
word1 = 'is nice';
var active, inactive;
var cooldown;
var font;
function preload() {
font = loadFont('data/LucidaSansRegular.ttf');
}
function setup() {
createCanvas(600, 300);
active = font.textToPoints(word0, 50, 200, 200);
inactive = font.textToPoints(word1, 50, 200, 200);
cooldown = 500;
for (var i = 0; i < active.length; i++) {
particles.push(new Particle(active[i].x, active[i].y));
}
}
function draw() {
background(60);
noStroke();
fill(255);
for (var i = 0; i < particles.length; i++) {
if (particle[i].radius < 0) {
particles.splice(i, 1);
continue;
}
if (cooldown < 0) {
particles[i].forceToDes();
} else {
particles[i].fleeFromDes();
}
particles[i].update();
particles[i].show();
}
if (cooldown < 500 && cooldown > -500) {
cooldown--;
} else {
cooldown++;
}
if (cooldown == -499) {
changeText();
}
}
function changeText() {
switchActive();
if (active.length == inactive.length) {
for (var i0 = 0; i0 < active.length; i0++) {
particles[i0].des = createVector(active[i0].x, active[i0].y)
}
} else if (active.length > inactive.length) {
for (var i1 = 0; i1 < particles.length; i1++) {
particles[i1].des = createVector(active[i1].x, active[i1].y);
}
for (var i2 = 0; i2 < active.length - inactive.length; i2++) {
var p = new Particle(active[i2].x, active[i2].y),
r = particles.random();
p.pos = r.pos;
particles.push(p);
}
} else {
for (var i3 = 0; i3 < inactive.length - active.length; i3++) {
var r = floor(random(particles.length));
particles[r].shrink();
}
for (var i4 = 0; i4 < particles.length; i4++) {
particles[i4].des = createVector(active[i4].x, active[i4].y);
}
}
}
function switchActive() {
var temp = active;
active = inactive;
inactive = temp;
}
I hope you can help me :)
Thank you already!
Please post your code as an MCVE that we can copy and paste to run. When I try to run your code, I get an error because I don't have the font you're trying to load. Either include the font file or modify your code so we don't need the font file.
But just looking at your code, this sticks out to me:
for (var i = 0; i < particles.length; i++) {
if (particle[i].radius < 0) {
Here you're looping over the particles array, but then using a variable called particle. This is probably a simple typo.
I'm also suspicious of this line:
r = particles.random();
Here you're setting a variable that you haven't defined yet.
When your code contains multiple errors like this, it usually means that you aren't testing in small chunks. You should really get into the habit of working in isolation, only testing one small part until you get that working perfectly. That also makes it easier to post an MCVE if you do get stuck.
Your problem is that your word1 string has a space in it.
textToPoints() doesn't handle non-printable characters.
Try a string with no space or split your string up into to strings and combine the points arrays afterwards.
On Line 1 You define:
var particles = [];
But then you do:
if (particle[i].radius < 0) {
You defined the array "particles", not "particle", so JavaScript can't read the first value as the array "particle" doesn't exist.
Solution:
change:
if (particle[i].radius < 0) {
to:
if (particles[i].radius < 0) {

Put a line break in a for loop that is generating html content

I have a for loop that is generating some HTML content:
var boxes = "";
for (i = 0; i < 11; i ++) {
boxes += "<div class=\"box\"><img src=\"unlkd.png\"/></div>";
}
document.getElementById("id").innerHTML = boxes;
I want to display 3 boxes in one row, then below them 2 boxes in one row, then 1, then 3 again, 2, and 1.
First i thought of using the if statement to check whether i > 2 to add a line break, but it will also add a line break after every box past the third one. Nothing comes to mind, and my basic knowledge of javascript tells me I'll have to make a loop for each row I want to make. Any advice?
I would use a different approch :
Use a array to store the number of item per row :
var array = [3, 2, 1, 3, 2];
Then, using two loops to iterate this
for(var i = 0; i < array.length; i++){
//Start the row
for(var j = 0; j < array[i]; ++j){
//create the item inline
}
//End the row
}
And you have a pretty system that will be dynamic if you load/update the array.
PS : not write javascript in a while, might be some syntax error
Edit :
To generate an id, this would be simple.
create a variable that will be used as a counter.
var counter = 0;
On each creating of an item, set the id like
var id = 'boxes_inline_' + counter++;
And add this value to the item you are generating.
Note : This is a small part of the algorithm I used to build a form generator. Of course the array contained much more values (properties). But this gave a really nice solution to build form depending on JSON
You can try something like this:
Idea
Keep an array of batch size
Loop over array and check if iterator is at par with position
If yes, update position and index to fetch next position
var boxes = "";
var intervals = [3, 2, 1];
var position = intervals[0];
var index = 0;
for (i = 0; i < 11; i++) {
boxes += "<div class=\"box\"><img src=\"unlkd.png\"/></div>";
if ((position-1) === i) {
boxes += "<br/>";
index = (index + 1) % intervals.length;
position += intervals[index]
}
}
document.getElementById("content").innerHTML = boxes;
.box{
display: inline-block;
}
<div id="content"></div>
var boxes = "",
boxesInRow = 3,
count = 0;
for (i = 0; i < 11; i ++) {
boxes += "<div class=\"box\"><img src=\"unlkd.png\"/></div>";
count++;
if(count === boxesInRow) {
boxes += "<br/>";
boxesInRow -= 1;
count = 0;
if (boxesInRow === 0) {
boxesInRow = 3;
}
}
}
document.getElementById("id").innerHTML = boxes;
var i;
var boxes = "";
for (i = 0; i < boxes.length; i++) {
boxes += "<div class=""><img src=""/></div>";
function displayboxes() {
"use strict";
for (i = 0; i < boxes.length; i++) {
out.appendChild(document.createTextNode(boxes[i] + "<br>"));
}
}
displayboxes(boxes);

Loop in javascript to append a series of divs

This is my code, but it does not work.
for (i = 0; i < 5; i++) {
$(function(){
$('.tt'+ [i]).appendTo('.td'+ [i]);
});
}
I want the result:
$('.tt1').appendTo('.td1')
$('.tt2').appendTo('.td2')
$('.tt3').appendTo('.td3')
$('.tt4').appendTo('.td4')
$('.tt5').appendTo('.td5')
Please correct me, thanks you in advance!
You have some syntax errors, try this:
for (var i = 0; i <= 5; i++) {
$('.tt'+ i).appendTo('.td'+ i);
}
As already mentioned: remove the array initialization.
If you want to iterate from 1 to 5 then do so (not var = 0, but var i = 1):
for (var i = 1; i < 6; i++) {
$('.tt'+ i).appendTo('.td'+ i);
}
Also I don't see any sense in wrapping it the appendTo call.
The 1st Thing
You will never jump into the i=5 iteration
$('.tt5').appendTo('.td5')
because your for loop
for (i = 0; i < 5; i++)
ends at i = 5
Change it to
for (i = 1; i <= 5; i++)
It starts at i=1 because your example didn't show a ".tt0"
The 2nd thing
Remote the brackets!
Change
$('.tt'+ [i]).appendTo('.td'+ [i]);
to
$('.tt'+ i).appendTo('.td'+ i);
Otherwise you will create an Array and the JS interpreter performs an unnecessary Array.toString() operation.
The 3rd thing
I think you can remove the surrounding function inside the for loop
$(function(){
...
}
Just use:
for (var i = 1; i <= 5; i++) {
$('.tt'+ i).appendTo('.td'+ i);
}
See Fiddle
http://jsfiddle.net/Spaghettirocker/knkpaczg/1/

I am trying to set bottom of element but its value is coming up NaN

function CheckavailOnload()
{
var elems = document.getElementsByClassName('box-collateral box-related');
var av = document.getElementsByClassName('availability in-stock');
var x;
for (var i = 0; i < elems.length; i++)
{
if (getComputedStyle(elems[i]).visibility == 'visible')
{
for (var j = 0; j < av.length; j++)
{
av[j].style.visibility = 'visible';
if(elems[i].offsetTop < 0)
{
var x = (elems[i].offsetHeight + (elems[i]).offsetTop).toString() + "px";
alert(x);
}
for(m = 0;m < av.length; m++)
{
av[m].style.Bottom = (-x);
return;
}
}
}
}
for (var k = 0; k < av.length; k++)
{
av[k].style.visibility = 'hidden';
}
var divs = document.getElementsByClassName('add-to-cart');
for(var l = 0; l < divs.length; l++)
{
divs[l].style.marginTop = (-500).toString() + "px";
divs[l].style.marginLeft = (-20).toString() + "px";
}
}
window.onload = CheckavailOnload;
here i am trying to move a paragraph tag have baground image depending upon the div offsetTop and Offset height div also have bacground image i am moving para tag just below the div but addition of offsetHeight and offsetTop is coming NAN please anyone can help me
You've declared var x; at the beginning of your script. Then later you're checking:
if(elems[i].offsetTop < 0) {
var x = (elems[i]...); // var is not recommended to be here, x has been already declared once
}
If elems[i].offsetTop happens to be >= 0, x will be undefined in this line:
av[m].style.Bottom = (-x); // Notice a typo here: should be av[m].style.bottom
This last expression gives you NaN. To avoid this, you need to either assign a default value to x in the beginning of the script, or add an else statement after the if wherein some numeric value is assigned to x.
Also return in the for...m-loop seems to break your code, the loop will never finish the job and the rest of the code will be never executed.
Using (-500).toString() + "px"; feels complex, why not just use "-500px";?

Categories

Resources