Loop through colours array with jQuery - javascript

I'm trying to give each div a different background colour. Here is my current code:
http://jsfiddle.net/Uy2FX/2/
var imgColours = ['#FCCF94', '#C4C9E5', '#ADE3D6'];
for (i=0; i < imgColours; i++) {
$('.img').css({backgroundColor: imgColours[0]});
}
However, I'm not quite sure where this is going wrong. I understand that's probably too simple to work, but in my mind it makes sense. Could someone point me in the right direction?

There are some relevant errors in your code.
This is probably what you wanted to do:
// V1 : Basic
var imgColours = ['#FCCF94', '#C4C9E5', '#ADE3D6'];
for (var i=0; i < imgColours.length; i++) {
$('.img:eq('+i+')').css({backgroundColor: imgColours[i]});
}
But if you want to get a random color from your array, for any number of divs, and also optimise your jQuery code a bit for better performance:
// V2 : random colors
var $imgs = $('#boxes1').find('.box'),
imgsCount = $imgs.length,
coloursCount = imgColours.length;
for (var i=0; i < imgsCount; i++) {
var rnd = Math.floor(Math.random() * coloursCount),
color = imgColours[rnd];
$imgs.eq(i).css({backgroundColor: color});
}
Or, if you want to loop through the colours following the order of the array, just change the loop:
// V3 : sequential colors
// Add V2 variables here
for (var i=0; i < imgsCount; i++) {
var color = imgColours[i%coloursCount];
$imgs.eq(i).css({backgroundColor: color});
}
UPDATED FIDDLE: http://jsfiddle.net/Uy2FX/12/
For some very basic tips on jQuery selectors performance: http://www.sitepoint.com/efficient-jquery-selectors/

You are always assigning imgColours[0] to EVERY div. I think what you are looking for is imgColours[i]
You will also need to use imgColours.length to tell your loop how long the array is.
You are also grabbing all HTML elements with the class of img, so this will change all of them each time.
To grab each element separately, you can use the CSS nth-of-type selector. Basically you can just do something like
$(".img:nth-of-type(" + i + ")")

You need to use imgColours.length
The for loop has no idea how long the array is otherwise
Edit: What's the point in this for loop if you end up using imgColours[0] anyways? If you want to loop each color, use i instead of 0.
And either way, this will not achieve a different background per div.
Try selecting by className (I'm going to use vanilla.js because it's simple)
var elements = document.getElementsByClassName("img");
for (var i = 0; i<elements.length; i++) {
var color = imgColours[Math.floor(Math.random()*imgColours.length)]; //get a RANDOM color change me if needed
elements[i].style.backgroundColor = color;
}

How about this?
var ec = 0;
var i = 0;
for(ec; ec < elements.length; ec++, i++) {
elements[ec].style.backgroundColor = imgColours[i];
if(i == (imgColours.length - 1)) i = -1;
}
http://jsfiddle.net/y2dq3/

Related

Array index out of bounds in Angular 2

I want to declare an Array with 4 dimensions, then loop some stuff with for() - and then the program breaks. Here is my code:
Typescript:
MoarInfo: any = [[[[]]]];
JavaScript:
constructor(){
for(var i = 0; i < this.AllDataInfo[this.KontoAktuellYearIndex][this.KontoAktuellMonth].length; i++){
for(var a = 0; a < this.AllDataInfo[this.KontoAktuellYearIndex][this.KontoAktuellMonth][i].length; a++){
for(var b = 0; b < this.AllDataInfo[this.KontoAktuellYearIndex][this.KontoAktuellMonth][i][a].length; b++){
this.MoarInfo[i][a][b][0] = this.AllDataInfo[this.KontoAktuellYearIndex][this.KontoAktuellMonth][i][a][b][0];
this.MoarInfo[i][a][b][1] = this.AllDataInfo[this.KontoAktuellYearIndex][this.KontoAktuellMonth][i][a][b][1];
this.MoarInfo[i][a][b][2] = 'DetailsSpan';
}
}
}
}
The Problem definitively lies at the MoarInfo[][][][] array. I tested my code without it, and it works fine. I tried the following possibilities for the Typescript array declaration as well:
Moarinfo: any[]; MoarInfo = []; MoarInfo = [[[[]]]]; MoarInfo: any[][][][] = [[[[]]]];
And in JavaScript, I tried to declare a new Array, and then push some elements on the MoarInfo array, with different functions (split, unshift, push, concat) and nothing worked.
What am I doing wrong?
Check the size of this.MoarInfo[i][a][b]. You are trying to get the value by index 0,1,2. Looks like its size is less than 2 which is causing this error.
if(this.MoarInfo[i][a][b].size > 0){
this.MoarInfo[i][a][b][0] = this.AllDataInfo[this.KontoAktuellYearIndex][this.KontoAktuellMonth][i][a][b][0];
}
if(this.MoarInfo[i][a][b].size > 1){
this.MoarInfo[i][a][b][1] = this.AllDataInfo[this.KontoAktuellYearIndex][this.KontoAktuellMonth][i][a][b][1];
}
if(this.MoarInfo[i][a][b].size > 2){
this.MoarInfo[i][a][b][2] = 'DetailsSpan';
}
Okay, I figured it out for myself. You have to set the elements of the dimensions from the array at first blank, then you can fill them with content. First I declared an Array in TypeScript like this AnArray = [];. Then I switched to JavaScript ( to the constructer() function ) and filled it with blank elements. I archieved this with this.AnArray.push();. If you want to set elements for the first dimension use push([]);, if you want an element for the 4th dimension, use push([[[]]]);. And you can set your content space like this push([[['E1',0,0,'E2']]]);. Now you can use follwing syntax:
alert( this.AnArray[0][0][0][3] ); //returns 'E2'
The complete code from my project now works fine and looks like this:
for(var i = 0; i < this.AllDataInfo[this.KontoAktuellYearIndex][this.KontoAktuellMonth].length; i++){
this.test.push([[[]]]);
for(var a = 0; a < this.AllDataInfo[this.KontoAktuellYearIndex][this.KontoAktuellMonth][i].length; a++){
this.test[i].push([[]]);
for(var b = 0; b < this.AllDataInfo[this.KontoAktuellYearIndex][this.KontoAktuellMonth][i][a].length; b++){
this.test[i][a].push(['',0,'']);
this.test[i][a][b][0] = this.AllDataInfo[this.KontoAktuellYearIndex][this.KontoAktuellMonth][i][a][b][0];
this.test[i][a][b][1] = this.AllDataInfo[this.KontoAktuellYearIndex][this.KontoAktuellMonth][i][a][b][1];
this.test[i][a][b][2] = 'DetailsSpan';
}
}
}
I wonder if there is a better way than using arrays, but if you want it too, you can do it like this.
cheers

Multiply an element by a number and insert using jQuery

I'm wondering if you can multiply an element using jQuery a number of times and insert it using .html()?
I am building my own slider which might help put things in context...
I am getting a number of times an element is used, which is stored in a var called eachSlideCount. So for example, this might output 10.
Then what I want to do is create a <span></span> for each of these (so 10 spans) and insert this into a div to generate a pager.
$this.next('.project-slider-count').html('<span></span>')
Is there anyway to muliply this span by the eachSlideCount number and then add to the .project-slider-count element?
I got this far... but clearly missing something...
var eachSlideCount = $this.find('.other-slides').length;
var eachSlideTotal = ($this.next('.project-slider-count').html('<span></span>')) * eachSlideCount;
$('.project-slider-count').html(eachSlideTotal);
Thanks in advance
Multiplication can only be done on numbers. If you want to repeat something, write a loop:
var span = '';
for (var i = 0; i < eachSlideCount; i++) {
span += '<span></span>';
}
$this.next('.projectslider-count').html(span);
In JavaScript, you can execute a for loop. For example, in the following:
var count = 10;
for (var i=0; i<count; i++) {
// Code
}
The body of the loop would be executed 10 times.
In jQuery, you can append a new HTML element inside an existing element using the append() method. For example, the following will add <span> elements in a loop:
var container = $("#container");
var count = 10;
for (var i=0; i<count; i++) {
container.append("<span>");
}
This is illustrated in a jsFiddle.

Adobe LiveCycle working with Repeating Subforms

I have repeating subforms with buttons on them.
I want to be able to remove buttons that have been added with each addition of a subform.
By the searching I've done, the following code should work, but it doesn't. Can someone please set me straight?
var IGdelbut = xfa.resolveNodes("ItemGroup[*].ItemHeader.Delbutton");
for (var i = 0; i < IGdelbut; i++) {
IGdelbut.presence = "invisible";
}
(I apologize for repeating my earlier question, but I'm hoping I'm giving someone better information to work with.)
Your script has a couple of issues iterating over the result of resolveNodes() call. If i get this right, you are trying to hide all the *DelButton*s on the subforms.
Try the following
var allDeleteButtons = xfa.resolveNodes("ItemGroup[*].ItemHeader.Delbutton");
var len = allDeleteButtons.length;
for (var i = 0; i < len; i++) {
allDeleteButtons.item(i).presence = "invisible";
}
Assuming you have this script on the parent subform of repeating ItemGroup subforms.

Inserting html elements while DOM is changing

My code should insert HTML content in all divs that have a predefined class name, without using jQuery and at least compatible with IE8 (so no getElementsbyClass).
The html:
<div class="target">1</div>
<div class="target">2</div>
<div class="target">3</div>
<div class="target">4</div>
The javascript:
var elems = document.getElementsByTagName('*'), i;
for (wwi in elems) {
if((' ' + elems[wwi].className + ' ').indexOf(' ' + "target" + ' ') > -1) {
elems[wwi].innerHTML = "YES";
//elems[wwi].innerHTML = "<div>YES!</div>";
}
}
You can try it here.
As you can see inside each div the word YES is printed. Well the if you comment elems[wwi].innerHTML = "YES"; and replace that for elems[wwi].innerHTML = "<div>YES!</div>" the code fails. I suppose is because inserting div elements modify the DOM and in consequence the FOR cycle fails. Am i right?
Well i can solve this pretty ugly by recalling the for cycle each time i make an innerHTML, and when i insert the code i can add a class (like data-codeAlreadyInserted=1) to ignore the next time the FOR pass in that div. But again, this is pretty much a very bad solution since for an average site with many tags I can even freeze the user browser.
What do you think? lets suppose i dont know the amount of tags i insert on each innerHTML call.
"I suppose is because inserting div elements modify the DOM and in consequence the FOR cycle fails. Am i right?"
Pretty much. Your elems list is a live list that is updated when the DOM changes. Because you're adding a new div on every iteration, the list keeps growing and so you never get to the end.
To avoid this, you can either do a reverse iteration,
for (var i = elems.length-1; i > -1; i--) {
// your code
}
or convert the list to an Array.
var arr = [];
for (var i = 0, len = list.length; i < len; i++) {
arr.push(elems[i]);
}
for (i = 0; i < len; i++) {
// your code
}
Another way is to use replaceChild instead of innerHTML. It works better and it's way faster:
var newEl = elem[wwi].cloneNode(false);
newEl.innerHTML = html;
elem[wwi].parentNode.replaceChild(newEl, elem[wwi]);
You can take a copy of the live node list:
var nodes = [];
for (var i = 0, n = elems.length; i < n; ++i) {
nodes.push(elems[i]);
}
and then use a proper for loop, not for ... in to iterate over the array:
for (var i = 0, n = nodes.length; i < n; ++i) {
...
}
for ... in should only be used on objects, not arrays.

Changing a class with z-index

I'm still in the process of learning JavaScript. and I would like to complete the task using only JavaScript and no Jquery.
I have multiple div/images that I’m trying to manipulate using the z-index, and a button that randomize the images to come to the front.
I got the random image array to work but as you could see in image[1]…setting each changeZ index will be laborious. So I’m embarking on changing the class’s (as seen in image[0] so I could add current to the new image and send current to the background on the next go around and then removing the class attribute. I have got the element to work separate but having trouble putting it together in a array.
function changeZIndex(i,id) {
document.getElementById(id).style.zIndex=i;};
function changeClassZIndex(i,tagName){
document.getElementsByTagName("*").style.zIndex=i;};
function getImage(){
var whichImage=Math.floor(Math.random()*3);
var image=new Array()
var currentPhoto = div.current
image[0]=function() {
changeZIndex(5,"scene1");
changeClassZIndex(-5,"current");
currentPhoto.removeClass('current')
document.getElementById("scene1").className += "current"; };
image[1]=function() {
changeZIndex(5,"scene2");
changeZIndex(-5,"scene1");
changeZIndex(-5,"scene3");
changeZIndex(-5,"scene");
};
image[2]=function() {
changeZIndex(5,"scene3");
changeZIndex(-5,"scene");
changeZIndex(-5,"scene2");
changeZIndex(-5,"scene1");
};
image[whichImage].apply(undefined);};
It's because document.getElementsByTagName() returns an array of elements, which you can't do operations like that on. Instead, you need to enumerate through them and do the operations individually.
Here's a working jsfiddle which shows exactly how to do it: jsfiddle
As a side note: if there's one thing a lot of web programming will teach you, its this:
Dont ever, ever, rule out jQuery as an option.
JQuery is your best friend, and the use of it in this situation would cut down your lines of code by well over half.
Firstly, I believe your problem is probably in changeClassZIndex(i,tagName)
which should probably look something like this:
if (document.getElementsByClassName == undefined) {
document.getElementsByClassName = function(className)
{
var hasClassName = new RegExp("(?:^|\\s)" + className + "(?:$|\\s)");
var allElements = document.getElementsByTagName("*");
var results = [];
var element;
for (var i = 0; (element = allElements[i]) != null; i++) {
var elementClass = element.className;
if (elementClass && elementClass.indexOf(className) != -1 && hasClassName.test(elementClass))
results.push(element);
}
return results;
}
}
function changeClassZIndex(z,className) {
var e = document.getElementsByClassName(className);
for(var i = 0; i < e.length; i++) {
e[i].style.zIndex = z;
}
};
I am defining the getElementsByClassName function if it does not exist because some browsers may not support it.
I may suggest taking a different approach to your problem however:
var images = new Array("scene1", "scene2", "scene3");
var currentPhoto = div.current
var whichImage = Math.floor(Math.random()*images.length);
// change all images to the background
for(var i = 0; i < images.length; i++)
{
changeZIndex(-5, images[i]);
}
// change the one you want to the top
changeZIndex(5, images[whichImage]);
That way you do not have to write functions for each image, and adding images is as easy as adding to the array.

Categories

Resources